读书笔记

  1. Ruby is Object-Oriented, Ruby是一门完全的面向对象语言。Ruby里的每个值都是对象
  2. 迭代器(iterator)行为类似于循环,包含在花括号中的代码称为代码块(block),它们与方法调用相关联并且充当了循环体的角色
  3. 数组(及类似的”可枚举”对象)定义了一个名为each的迭代器,它为数组里的每一个元素调用一次相关联的代码块,每次对代码块的调用都以数组里的一个元素作为参数。
  4. Hash基于哈希表数据结构,用于将任意的键对象映射到值对象。哈希使用键对象作为索引。
  5. Ruby的哈希可以使用任何对象作为键,但是Symbol对象是最为常用的。符号(symbol)是不可变的,功能受限的字符串,可以通过气身份来对符号进行比较,而非通过其文本内容(因为两个不同的Symbol对象是绝对不会包含同样的内容的)
  6. Def关键字来定义方法,方法的返回值是方法体中最后一个呗执行的表达式的值
  7. 如果将方法定义在类或模块(module)之外,那么它就是一个全局函数,而不是一个方法(须要通过某个对象来调用方法)
  8. 可以专门为某个对象定义方法,只要以对象名为方法名的前缀,这样的方法称为单键(singleton)方法。
  9. Ruby的特性:类和模块都是“开放的”,而且可以在运行时修改和扩展
  10. Ruby允许其方法返回多个值。
  11. Ruby中的方法可以以问好或感叹号结尾,问号被用于标示谓词,即返回Boolean值的方法。出现在方法名尾部的感叹号表明使用该方法时需要多加小心。不带感叹号的方法返回调用该方法的对象的一个修改过的拷贝,而带感叹号的方法则是一个可变方法,该方法会修改原对象。
  12. 全局变量以$为前缀,实例变量以@为前缀,类变量以@@为前缀
  13. Regexp(正则表达式)对象,它描述了一个文本模式并且含有方法来判断一个给定的字符串是否匹配该模式
  14. 一个类就是一些相关方法的集合,这些方法将操作一个对象的状态。一个对象的状态被保存在它的实例变量中:即那些以@开头的变量,其值是特定于该对象的。
  15. Ruby的字符串是可变的, []=操作符允许你改变一个字符串中的字符,或者插入、删除及替换子字符串,<<操作符允许你在一个字符串的后面追加一些东西,而且String类还定义了各种其他的方法对字符串进行就地的更改。
  16. 因为字符串是可变的,所以字符串字面量在程序中并不是独一无二的对象。
  17. 如果你在一个循环内包含了一个字符串字面量,那么每次循环都会为它创建一个新的对象。通过在一个字符串(或任何对象)上调用freeze方法,你可以防止将来该对象的任何改变。
  18. Nil值被当做false来处理,而任何其他值都和true一样处理。
  19. –e命令行选项使解释器执行一行指定的Ruby代码
  20. Puts将一个文本字符串打印到控制台并在其后添加一个换行符,如果传递给puts的对象不是一个字符串,那么puts就调用该对象的to_s方法,并且打印该方法所返回的字符串
  21. Print方法和puts方法做的基本是同一件事情,但是它不在末尾添加一个换行符
  22. Gem list: list installed gems
  23. Gem update: update all installed gems
  24. Gem update –system: update rubygems itself
  25. 在Ruby1.9中,关键字__ENCODING__含有当前正在执行的代码的源编码,其结果值是一个Encoding对象。
  26. 源编码会告诉Ruby解释器如何解读一个脚本中的字符。通常采用编码注释来设定一个文件的源编码,一个Ruby程序可以包含多个文件,不同的文件可以采用不同的源编码。
  27. 默认外部编码是当Ruby从文件或流中读取内容时采用的默认编码。默认外部编码对于Ruby进程来说是全局性的,而且不会随着文件的不同而改变。通常情况下,默认外部编码是基于你的电脑区域设置来进行设置的。默认外部编码并不改变字符串字面量的编码方式。
  28. Ruby里不存在一个作为程序运行入口点的main方法。Ruby接受一个待执行语句的脚本,然后从第一行代码开始一直执行到最后一行。
  29. Ruby使用String类的对象表示文本。
  30. 在Ruby1.9中,通过\u转义序列,由双引号引用的字符串可以包含任意的Unicode字符
  31. 当使用反引号(即`字符)来引用文本时,该文本被作为一个由双引号引用的字符串字面量来处理。该文本的值将被传递给一个特殊的名为Kernal.`的方法,该方法将该文本的值作为一个操作系统shell命令来执行,并且将该命令的输出作为字符串返回。
  32. String.new方法来创建新字符串,在没有参数的情况下,此方法会返回一个不包含字符的新字符串。如果有一个字符串作为其参数,那么该方法将会返回一个新的String对象,它含有和参数字符串一样的文本。
  33. 在Ruby1.9及其后的版本,字符就是长度为1的字符串。
  34. Ruby里的+操作符不会将其右侧操作数自动地转换成字符串
  35. <<操作符会将其第二个参数添加到第一个参数后面,这个操作符不同于+,它会修改左侧的操作符
  36. 与+类似,<<操作符也不会对右侧操作数做任何的类型转换,但是,如果右侧操作数是一个整数,那么它将被作为一个字符编码来处理,对应的操作符将被添加到左侧操作符上。
  37. 如果你试图访问一个超出了字符串末尾的字符,Ruby并不会抛出异常,只是简单地返回nil
  38. 在Ruby1.9中,当你索引单个字符时,会返回一个由单个字符组成的字符串,而不是该字符的编码值
  39. 当使用一个Range对象来索引一个字符串时,其返回值就是由位于此Range内的字符所构成的子字符串
  40. 如果一个字符串包含了多字节字符,那么其字节数量就不等于字符数量,在Ruby1.9中,length和size方法都返回一个字符串的字符数,而新的bytesize方法则返回字节数
  41. 一个字符串字面量的编码方式基于其所在的文件的源编码,但是该字符串的编码也不总是和源编码保持一致的。
  42. Encoding对象充当了编码方式的标识符
  43. 在Ruby中,数组的第一个值的索引为0,size和length方法返回一个数组中的元素个数。数组中最后一个元素的索引是size-1, 负索引值将从数组的末尾开始计数,如果试图越界读取数组元素,Ruby会返回nil而不会抛出异常
  44. Ruby的数组是无类型且可变的,数组里的元素不必都属于同一个类型,而且它们可以随时改变。此外,数组的大小也是可以动态改变的,你可以向数组添加元素,数组会按需增长。如果你向一个超出数组末尾的元素进行赋值,数组将会动态增长,而且用nil来填充那些多出来的位置
  45. 一个数组字面量就是一个由逗号分隔的值所构成的列表,位于一对方括号内
  46. 哈希是一种数据结构,它维护 了一个键对象集合,而且将每个键都与一个值关联起来。
  47. 一个哈希字面量就是一列由逗号分隔的键/值对,被包含在或括号中。键和值之间由双字符的”箭头”操作符=>来分隔。
  48. Symbol是不可改变的、功能受限的字符串,编写成以冒号为前缀的标识符
  49. Ruby里的哈希是采用一种称为哈希表的数据结构来实现的,那些作为哈希键的对象必须有一个hash方法,该方法为该键返回一个Fixnun的哈希码。如果两个键相等,那么它们必须具有相同的哈希码。
  50. Hash类采用eql?方法比较键之间的相等性。对于大多数Ruby类来讲,eql?方法与==操作符一样。如果在所定义的新类里面重写了eql?方法,那么你必须同时重写hash方法,否则你的类实例将无法作为一个哈希键
  51. 对所有那些作为键的字符串,Ruby会为其生产私有拷贝。在使用其他任何可变对象作为哈希键时,必须非常小心谨慎。要考虑为这些可变对象生产私有拷贝,或者调用freeze方法。如果你必须使用可变的哈希键,则在每次更改键之后,调用Hash类的rehash方法
  52. 一个Range对象表示位于一个开始值和一个结束值直接的一些值。范围字面量的表现形式是在开始和结束值之前放置二三个点。如果使用两个点,那么该房屋就是包含性的,结束值将是该范围的一部分。如果使用三个点,那么该范围就是排他性的,结束值将不是范围的一部分。
  53. 一个Ruby解释器的典型实现会维护一个符号表(symbol table),在这个表中,它存储了其所知晓的所有类、方法及变量的名称。使一个这样的解释器可以避免大多数的字符串比较
  54. 两个字符串可能包含相同的内容,但是它们是两个完全不同的对象,对于符号来讲,这是不可能的。两个拥有相同内容的字符串都会转换成同一个Symbol对象,两个不同的Symbol对象总是罕有不同的内容。
  55. 当你使用字符串的目的在于将其作为一种独一无二的标识符,而不在于它们的文本内容时,请改用符号。
  56. True是TrueClass类的一个单键实例,同样地,false和nil分别是FalseClass和NilClass类的单键实例。注意,Ruby没有Bollean类,TrueClass和FalseClass的超类都是object
  57. Ruby所有值都是对象,而且没有基本类型和对象类型的区别。在Ruby中,所有对象都继承一个Object类,而且共享那些定义于此类的方法
  58. 当我们在Ruby中使用对象时,其实是在使用对象引用。我们操作的是对象的一个引用,而非对象本身。当我们将一个值赋给一个变量时,我们并没有将一个对象拷贝到该变量中,而是在此变量中存储了一个指向那个对象的引用
  59. 在Ruby中,当把一个对象传递给一个方法时,其实传递的是该对象的引用,被传递的既不是对象本身,也不是一个指向该对象的引用的引用。换言之,方法实参是通过值而不是引用来传递的,只不过被传递的值刚好是对象的引用。因为对象引用被传递给方法,所以方法可以利用这些引用来修改底层的对象。在方法调用返回之后,还可以见到这些修改的结果
  60. Fixnum和Symbol都没有可变方法,所以它们都是不可变的。
  61. 立即值和引用值的唯一差别在于:不能为立即值定义单键方法。
  62. New是Class类的一个方法,它首先为新对象分配内存,然后通过调用该对象的initialize方法初始化这个新建的”空”对象的状态,传递给new方法的参数直接被传递给initialize方法。大多数类都定义了一个initialize方法,用于完成任何对于实例来说必须的初始化工作。
  63. New和initialize方法是创建对象的默认技术,但是类也可以定义其他一些被称为”工厂方法”的方法来返回其实例
  64. Ruby永远不须要显示释放对象,Ruby采用了垃圾收集的技术来自动销毁那些不再需要的对象。
  65. 每个对象都有一个对象标识符,它是一个Fixnum,而且你可以通过object_id方法来获得。该方法的返回值在该对象的生命周期中是独一无二且恒久不变的,只要该对象是可访问的,它就会一直持有一个同样的ID,而且其他对象也不会共享这个ID。
  66. 在Ruby中,每个对象都属于一个定义良好的类(class),而且该类在此对象的生命周期中永远不变。
  67. Equal?方法由Object定义,用于测试两个值是否引用了同一个对象。对于两个不同的对象,该方法始终返回false。按照惯例,子类永远不要会重写equal?方法
  68. ==操作符,在Object类里,它是equal?方法的同义词,用于比较两个对象引用是否是同样的
  69. Hash采用eql?检查两个哈希键是否相等,如果两个对象通过eql?比较的结果是真,那么它们的hash方法也必须返回相同的值。
  70. ===操作符通常被称为“条件相等性”操作符,用于测试一个case语句的目标值是否和某个when从句相匹配
  71. 在Ruby里,类似于0、0.0以及空字符串””的值都表现得像true一样。
  72. Clone和dup方法都返回一个调用它们对象的浅拷贝,如果被拷贝的对象含有指向其他对象的引用,那么只有这些引用被拷贝,而那些被引用的对象本身却不会被拷贝
  73. 可以调用freeze方法将任何对象冻结起来,一个被冻结的对象将变得不可改变---它所有的内部状态都不能改变,而且对其可变方法的调用也会失败。
  74. 如果一个类被冻结,那么将无法再向该类添加任何方法
  75. 一个表达式就是一块Ruby代码,Ruby解释器可以对其求值并得到一个结果
  76. 一个变量就是一个值的名字。以$开头的变量是全局变量,在整个Ruby程序里都是可见的。以@或@@开头的变量分别是实例变量和类变量,用于面向对象编程。以一个下划线或小写字符开头的变量是局部变量,它们仅在当前方法或代码块内定义。
  77. 在对象之外,Ruby的实例变量是永远不可见的,而且实例变量名永远不会被对象名来限定修饰
  78. 代码块不会单独存在,它们只有出现在一个方法调用之后才是合法的
  79. 一个代码块的“返回值”就是它里面最后执行的那个表达式的值。
  80. 代码块定义了一个新的变量作用域,在一个代码块内定义的变量仅存在于该代码块内,在其之外就没有定义了。
  81. Return语句使其方法返回到其调用者
  82. Throw不但可以跳出当前的循环或代码块,而且可以向外跳出任意级数,使与catch一同定义的那个代码块退出。
  83. 如果一个throw没有被调用,那么对应的catch调用就会返回其代码块中最后一个表达式的值。如果一个throw被调用了,那么默认情况下,对应的catch的返回值为nil
  84. 异常对象都是由raise方法创建的,但是你可以通过new方法,或者另一个名为exception的类方法来创建自己的异常对象。
  85. Ruby解释器按照rescue从句编写的顺序来匹配异常
  86. 当一个异常发生时,程序的控制权会立刻向外和向上传递,直到找到一个合适的rescue从句来处理该异常。
  87. 一个方法异常退出,和正常的返回是不一样的。该方法没有返回值,而且异常对象会从调用该方法的地方开始继续传播。异常向外传播,试图在外围代码块里查找一个能处理它的rescue从句。如果找不到这样的rescue语句,那么该方法就返回到它的调用者。
  88. 无论begin从句中的代码发生了什么事,ensure从句中的代码都会被执行
  89. 如果一个begin语句没有传播一个异常,那么该语句的值就是begin、rescue或else从句中最后执行的那个表达式的值,ensure从句中的代码保证被执行,但是不会影响到begin语句的值
  90. 一个执行线程就是一个Ruby语句序列,其执行过程和Ruby解释器所执行的主语句序列的执行过程是并行的。Ruby用Thread对象表示线程
  91. 通过Thread对象的value方法可以获得代码块的返回值
  92. 生成器是一种对象,它们可以先计算出一个部分结果,然后将该结果返回给调用者并保存计算的状态,使将来调用者可以恢复计算并获取下一个结果。
  93. 可以使用Fiber.new来创建一个纤程,并且给它一个代码块来指定需要执行的代码。与纤程不同的是,一个纤程的代码体不会立刻被执行,你须要调用那个代表该纤程的Fiber对象的resume方法来开始该纤程的运行
  94. 通过resume和yield方法 的实参和返回值,纤程可以和其调用者交换数据。第一次调用resume时的实参将被传递给与该纤程相关的代码块,它们成为代码块形参的值。在后续调用中,resume的实参值将成为Fiber.yield的返回值。相反地,Fiber.yield的实参值成为resume的返回值。当纤程的代码块结束时,最后一个被执行的表达式的值将成为resume的返回值。
  95. 在调用者代码中,将传递给纤程的消息始终作为resume方法的实参,而来自纤程的反馈则是该方法的返回值。在纤程体中,纤程所接受的消息,除第一条外,都来自Fiber.yield的返回值。此外,在所有反馈中,除了最后一条,都是Fiber.yield的实参。纤程所接受的第一条消息是通过代码块的形参得到的,最后一条反馈则来自代码块的返回值。
  96. Return关键字将在到达方法最后一个表达式前强行返回,如果一个表达式跟在return关键字之后,它的值会作为方法返回值。如果return后面没有任何表达式,那么返回值为nil
  97. Ruby方法可以返回多个值,这需要显式使用return语句,并把要返回的值用逗号分开
  98. 方法永远是在一个对象上调用的。在方法代码中,self代表方法诶调用的对象。如果调用方法时不指定对象,这表示该方法在self上被调用
  99. 一个Ruby方法可以有两个名字,但是两个方法不能共享一个名字。
  100. Proc的行为与代码块类似,而lambda的行为与方法类似,不过,它们都是Proc类的实例
  101. 在Ruby中,proc和lambda都是闭包,它表示一个对象既是一个可调用的函数,同时也是绑定在这个函数上的一个变量。当创建一个proc或lambda时,得到的Proc对象不仅包含了可执行的代码块,也绑定了代码块中所使用的全部变量
  102. Ruby中的每个值都是一个对象。每个对象都是某个类的一个实例,类定义了一个对象需要响应的一组方法。类可以扩展或子类化其他类,从而继承或重载父类中的方法。类还可以包含模块,或者从中继承方法。
  103. 类对象的new方法在创建一个实例后,自动调用该实例的initialize方法,传给new方法的所有参数被传递给initialize方法。
  104. 对象的实例变量只能被该对象的实例方法访问。实例方法外的代码不能对实例变量进行读写操作
  105. 任何自定义的类都应该定义一个to_s实例方法,用来返回代表该对象 的字符串
  106. 私有方法不能在所定义的类外被调用,但是它们会被子类继承,这意味着子类可以调用它们,也可以覆盖它们
  107. 在Ruby中,对象通常通过类的new方法来创建
  108. 每个类都继承了new这个类方法。这个方法要进行两项工作:它必须分配一个新对象,即让这个对象存在,并初始化这个对象。这两项工作,它分别交给allocate和initialize方法来实现。
  109. Allocate是Class类的一个实例方法,被所有类对象所继承,它的作用在于创建类的一个实例。
  110. Initialize是一个实例方法,绝大多数的类都需要这个方法。每个不是从Object继承而来的类都应该使用super来链式调用超类的initialize方法,initialize方法的一般性工作就是创建该对象的实例变量并为它们赋初始值。通常,客户端代码为new方法传递参数,这些参数将再次被传给initialize方法,然后赋值给这些实例变量。Initialize方法无须返回一个初始化后的对象。
  111. 如果一个了定义了一个名为initialize_copy方法,那么clone和dup方法在拷贝完实例变量后,在新创建的对象上执行这个方法
  112. 当clone和dup方法把实例变量从原始对象拷贝到拷贝对象中时,它们拷贝的是引用而非实际值
  113. 单键是指仅仅拥有一个实例的类
  114. Load把一个文件加载多次,而require则试图避免对同一个文件的多次加载
  115. Ruby的加载路径是一个数组,可以通过全局变量$LOAD_PATH或者$:进行访问。数组的每个元素都是一个目录名
  116. 反射,也称为内省,表示一个程序可以审视自身的状态和结构
  117. 一个Binding对象代表某一时刻Ruby变量的绑定状态,Kernal.binding返回调用时实际发生的绑定,
  118. =~是Ruby基本的模式匹配操作符。一个操作数必须是一个正则表达式,而另一个则必须是一个字符串。=~操作符会检查字符串操作数,看它或它的子字符串是否与指定的正则表达式匹配。如果发现了一个匹配,=~操作符将返回第一个匹配在字符串中的位置,否则返回nil
  119. 一个IO对象就是一个流,它是一个可读的信息源,内容可以是字节、字符或字节(或字符)的可写池