<Ruby编程语言_涵盖Ruby 1.8和1.9>读书笔记

  1. Ruby是面向对象的,Ruby里的每个值都是对象
  2. 包含在花括号中的代码被称为代码块
  3. 数组定义了一个each的迭代器,它为数组里的每一个元素调用一次相关联的代码块,每次对代码块的调用都以数组里的一个元素作为参数
  4. 哈希是Ruby里的基础数据结构,它们基于哈希表数据结构,用于将任意的键对象映射到值对象。
  5. Hash类定义了一个each迭代器方法。这个方法为哈希里的每一个键/值对调用一次相关联的代码块,并且将键和值都作为参数传递给代码块。
  6. Ruby的哈希可以使用任何对象作为键,但是Symbol对象是最为常用的
  7. 符号(symbol)是不可变的,功能受限的字符串,可以通过其身份对符号进行比较,而非通过其文本内容(因为两个不同的Symbol对象是绝对不会包含同样的内容的)
  8. 用def定义方法,方法的返回值是方法体中最后一个被执行的表达式的值
  9. 如果将方法定义在类或模块之外,那么它就是一个全局函数,而不是一个方法(须要通过某个对象来调用方法)。还可以专门为某个对象定义方法,只要以对象名为方法名的前缀即可,这样的方法被称为单键(singleton)方法
  10. Ruby中的方法还可以以问好或感叹号结尾,问号被用于标示谓词,即返回Boolean值的方法。出现在方法名尾部的感叹号表明使用该方法时需要多加小心。
  11. 许多Ruby核心类都定义了成对的方法,它们具有同样的名字,彼此的差别在于其中一个以感叹号结尾,而另一个没有。通常情况下,不带感叹号的方法返回调用该方法的对象的一个修改过的拷贝,而带感叹号的方法则是一个可变方法,该方法会修改原对象。
  12. 全局变量以$为前缀,实例变量以@为前缀,类变量以@@为前缀
  13. Regexp(正则表达式)对象,它描述了一个文本模式并且含有方法来判断一个给定的字符串是否匹配该模式
  14. Range,代表了位于两个端点之间的值
  15. 一个类就是一些相关方法的集合,这些方法将操作一个对象的状态。一个对象的状态被保存在它的实例变量中:即那些以@开头的变量,其值是特定于该对象的。
  16. Ruby的字符串是可变的,[]=操作符允许你改变一个字符串中的字符,或者插入、删除及替换子字符串。<<操作符允许你在一个字符串的后面追加一些东西
  17. 因为字符串是可变的,所以字符串字面量在程序中并不是独一无二的对象。如果你在一个循环内包含了一个字符串字面量,那么每次循环都会为它创建一个新的对象。通过在一个字符串(或任何对象)上调用freeze方法,你可以防止将来该对象的任何改变
  18. Nil值被当成false来处理,而任何其他值都和true一样处理
  19. Puts将一个文本字符串打印到控制台并在其后添加一个换行符(除非该字符串已经以一个换行符结尾了)。如果传递给puts的对象不是一个字符串,那么puts就调用该对象的to_s方法,并且打印该方法所返回的字符串。Print和puts基本类似,但是它不在末尾添加一个换行符 。
  20. Gem list: list installed gems
  21. Gem environment: Display RubyGems configuration information
  22. Gem update rails: update a named gem
  23. Gem update: update all installed gems
  24. Gem update –system: update RubyGems itself
  25. Gem uninstall rails: remove an installed gem
  26. 如果你编写的程序需要使用一些以gem形式安装的模块,那么在require这些模块之前,必须首先require ‘rubygems’。 Rubygem是模块的载入将改变require方法本身,使它在搜索标准库之前先搜索由安装过的gems所组成的集合。
  27. Ruby中的注释以#字符开头并持续到该行结束。但如果#字符出现在一个字符串或正则表达式字面量里,那么它将作为此字符串或正则表达式的一部分,而非引入一段注释
  28. 字面量就是那些直接出现在Ruby源代码里的值。字面量包括数字、文本字符串及正则表达式
  29. 一个标识符就是一个名字。Ruby利用标识符对变量、类及方法之类的东西进行命名
  30. Ruby是大小写敏感的语言
  31. 体就是一个语句列表。该列表包括类定义、方法定义体、while循环体等诸如此类的结构。
  32. 默认情况下,Ruby解释器假定程序的编码是ASCII
  33. 在Ruby1.9中,关键字__ENCODING__含有当前正在执行的代码的源编码,其结果值是一个Encoding对象
  34. 源编码会告诉Ruby解释器如何解读一个脚本中的字符。通常采用编码注释来设定一个文件的源编码。一个Ruby程序可以包含多个文件,不同的文件可以采用不同 的源编码。
  35. 默认外部编码是不同的,它是当Ruby从文件或流中读取内容时采用的默认编码。默认外部编码对于Ruby进程来说是全局性的,而且不会随着文件的不同而改变。
  36. Ruby中的所有数字对象都是Numeric类的实例。所有的整数都是Integer类的实例。
  37. Ruby使用String类的对象表示文本。字符串是可变的对象
  38. Here document以<<或<<-开头,后面紧跟一个用于指定结尾分界符的标识符或字符串,从下一行开始直至该分界符单独出现在一行为止,其间的文本都被作为该字符串字面量的内容。
  39. 当使用反引号(`字符)来引用文本时,该文本被作为一个由双引号引用的字符串字面量来处理。该文本的值将被传递给一个特殊的名为Kernal.`的方法,该方法将该文本的值作为一个操作系统shell命令来执行,并且将该命令的输出作为字符串返回。
  40. Ruby支持一种泛型化的引用语法,可以用来替代反引号。%s[ls]
  41. Ruby的字符串是可变的。每当Ruby遇见一个字符串字面量时,它都会新建一个对象。如果你在一个循环体内包含了一个字面量,那么Ruby在每次迭代的时候都会创建一个新的对象。
  42. String.new方法来创建新字符串,在没有字符串的情况下,此方法会返回一个不包含字符的新字符串。如果有一个字符串作为其参数,那么该方法将会返回一个新的String对象,它含有和参数字符串一样的文本。
  43. 在Ruby程序中,可以通过在字符前加一个问号的方式来表示单个字符构成的字面量,不需要使用任何形式的引号
  44. +操作符用于将两个字符串连接起来,并将结果作为一个新字符串对象返回。
  45. Ruby里的+操作符不会将其右侧操作数自动转换成字符串
  46. ==和+=用于比较字符串之间的相等性和不等性。当且仅当两个字符串拥有相同的长度,而且所有字符都相等时它们才是相等。
  47. 如果从字符串的末尾开始计算索引。那么数组索引就是负值,而且从-1开始,自右向左依次减少。如果你试图访问一个超出了字符串末尾的字符,Ruby并不会跑出异常,只是简单地返回nil
  48. Each_byte按字节对一个字符串进行顺序的迭代,each_char按字符进行迭代,each_line按行迭代。
  49. 在Ruby1.9中,length和size方法都返回一个字符串的字符数,而新的bytesize方法则返回字节数
  50. Ruby1.9的String类定义了一个encoding方法,用于返回一个字符串的编码方式
  51. 如果你有一个字符串形式的编码名称,而且希望获得对应的Encoding对象,可使用Encoding.find工厂方法
  52. Encoding.list方法返回一个由Encoding对象构成的数组,Encoding.list方法只列出内建的编码及任何已经动态载入的编码
  53. 一个数组就是一系列的值,可以通过这些值在该序列中的位置或索引来访问它们。在ruby中,数组的第一个值的索引为0,size和length方法返回一个数组中的元素个数,数组中最后一个元素的索引是size-1。 负索引值从数组的末尾开始计数,索引-1访问数组的最后一个元素,倒数第二个元素的索引为-2.如果试图读取一个超出数组范围的元素,Ruby将返回nil而不是抛出异常
  54. Ruby的数组是无类型且可变的,数组里的元素不必都属于同一个类型,而且它们可以随时改变。此外,数组的大小也是可以动态改变的
  55. 一个数组字面量就是一个由逗号分隔的值所构成的列表,位于一对方括号内
  56. 一个哈希字面量就是一列由逗号分隔的键/值对,被包含在花括号中。
  57. 一个Range对象表示位于一个开始值和一个结束值之间的一些值。
  58. 两个字符串可能包含相同的内容,但是它们是两个完全不同的对象,对于符号来讲,这是不可能的,两个拥有相同内容的字符串都会转换成同一个Symbol对象,两个不同的Symbol对象将总是含有不同的内容。
  59. Nil是一个特殊的保留着,用于表示没有值。True是TrueClass的一个单键实例。Ruby没有Boolean类,TrueClass和FalseClass的超类都是Object
  60. 在Ruby中,所有对象都继承一个Object类,而且共享那些定义于此类中的方法。
  61. 当我们在Ruby中使用对象时,其实是在使用对象引用。我们操作的是对象的一个引用,而非对象本身。当我们将一个值赋给一个变量时,我们并没有将一个对象拷贝到该变量中,而是在此变量中存储了一个指向那个对象的引用
  62. 在Ruby中,当把一个对象传递给一个方法时,其实传递的是该对象的引用,被传递的既不是对象本身,而不是一个指向该对象的引用的引用。方法实参是通过值而不是引用来传递的,只不过被传递的值刚好是对象的引用。
  63. 因为对象引用被传递给方法,所以方法可以利用这些引用来修改底层的对象。在方法调用返回之后,还可以见到这些修改的结果
  64. New是Class类的一个方法,它首先为新对象分配内存。然后通过调用该对象的initialize方法初始化这个新建的”空”对象的状态,传递给new方法的参数直接被传递给initialize方法。大多数类都定义了一个initialize方法,用于完成任何对于实例来说必须的初始化工作。
  65. 每个对象都有一个对象标识符,它是一个Fixnum,而且你可以通过object_id方法来获得。该方法的返回值在该对象的生命周期中是独一无二且恒久不变的,只要该对象是可访问的,它就会一直持有一个同样的ID,而且其他对象也不会共享这个ID。
  66. 检查一个对象所属的类的一种非常直接的方法就是通过直接比较:o.class == String,或使用instance_of?
  67. Equal?方法由Object定义,用于测试两个值是否引用了同一个对象,对于两个不同的对象,该方法始终返回false
  68. 另一种检查两个对象是否是同一个对象的方法是比较它们 的object_id
  69. ===操作符通常被称为”条件相等性”操作符,用于测试一个case语句的目标值是否和某个when从句相匹配
  70. Clone和dup方法都返回一个调用它们的对象的浅拷贝,如果被拷贝的对象含有指向其他对象的引用,那么只有这些引用被拷贝,而那些被引用的对象本身却不会被拷贝
  71. Clone方法会拷贝一个对象的被冻结(frozen)和受污染(tainted)状态,而dup方法仅仅拷贝受污染状态。在一个被冻结的对象上调用dup方法将返回一个未被冻结的副本。其次,clone方法会拷贝对象的所有单键方法,而dup则不会。
  72. 可以调用freeze方法将任何对象冻结起来。一个被冻结的对象将变得不可改变—它所有的内部状态都不能被改变,而且对其可变方法的调用也会失败。
  73. 如果一个类被冻结,将无法向该类添加任何方法
  74. 一个表达式就是一块Ruby代码
  75. 在对象之外,Ruby的实例变量是永远不可见的,而且实例变量名永远不会被对象名限定修饰
  76. &&的优先级高于||
  77. Unless和if恰恰相反,当且仅当其关联的表达式的值为false或nil时,它才会执行相应的代码
  78. Times、each、map及upto方法都是迭代器,它们和紧随其后的代码进行交互,。Yield语句就是这些迭代器背后复杂的空值结构。
  79. Collect方法(也被称为map)为那个调用它的可枚举对象的每个对象执行相关联的代码块,并且将所有返回值组合到一个数组中,然后再返回
  80. Select方法为那个调用它的可枚举对象的每个元素执行相关联的代码块,如果代码块的返回值不是false或nil,那么该元素就会被选中,最后select将所有被选中的元素组合成一个数组并返回
  81. Reject方法和select方法恰好相反,它返回那些使代码返回nil或false的元素
  82. Inject方法用两个参数调用相关联的代码块,第一个参数是一个来自此前的迭代的累计值,第二个参数则是那个调用它的可枚举对象的下一个元素。如果当前迭代不是最后一次迭代,那么其代码块的返回值就成为下一次迭代的第一个参数,否则,就成为inject迭代器的返回值。如果在调用inject的时候传给它一个参数,那么该参数成为累计值变量的初始值,否则,就使用那个可枚举对象的第一个元素作为累计值变量的初始值。
  83. 一个枚举器是一个Enumerable对象,其目的在于枚举其他的对象。
  84. 一个代码块的”返回值”就是它里面最后执行的那个表达式的值
  85. 代码块定义了一个新的变量作用域:在一个代码块内定义的变量仅存在于该代码块内,在其之外就没有定义了
  86. Throw不但可以跳出当前的循环或代码块,而且可以向外跳出任意级数,使与catch一同定义的那个代码块退出
  87. 异常等一下典型地都是由raise方法创建的,但是你可以通过new方法,或者另一个名为exception的类方法来创建自己的异常对象。
  88. 全局变量引用了当前正在处理的Exception对象。
  89. 如果在执行一个rescue从句的过程中发生了一个新的异常,那么原先被处理的那个异常被丢弃,新的异常从它产生的地方开始传播。
  90. 无论begin从句中的代码发生了什么事,ensure从句中的代码都会被执行
  91. 一个执行的线程就是一个Ruby语句序列,其执行过程和Ruby解释器所执行的主语句序列的执行过程是并行的
  92. 调用Thread.new并给它一个代码块即可,这会创建一个新的执行线程并且开始执行代码块中的代码。于此同时,原先的线程从Thread.new的调用中返回并且继续执行后续的语句。当代码块中的语句被执行完毕,新线程就会结束。通过Thread对象的value方法可以获得代码块的返回值
  93. Fiber(协同例程)最常见的用法是实现生成器, 生成器是一种对象,它们可以先计算出一个部分结果,然后将结果返回给调用者并保存计算的状态,使将来调用者可以恢复计算并获取下一个结果。
  94. 和线程一样,一个纤程也具有一个代码体。你可以用Fiber.new来创建一个纤程,并且给它一个代码块来指定需要执行的代码。与线程不同的是,一个纤程的代码体不会立刻被执行,你须要调用那个代表该纤程的Fiber对象的resume方法来开始该纤程的运行。在第一次调用一个纤程的resume方法时,程序控制权被传递到纤程体的起始部分,然后该纤程开始运行,直到运行完整个纤程体或遇到Fiber.yield这个类方法为止。Fiber.yield方法把程序控制权传回给调用者,使得对resume的调用返回。它还将保存纤程的状态,这样一来当下次调用resume方法时,该纤程就可以从上次离开的地方开始运行。
  95. 创建一个纤程不会立即执行其纤程体
  96. Fiber.yield将控制权从当前的线程传回其调用者,而yield语句则将控制权从一个迭代器方法传递给与其相关的代码块。
  97. 通过resume和yield方法的实参和返回值,纤程可以和其调用者交换数据。第一次调用resume时的实参将被传递给与该纤程相关的代码块,它们成为代码块形参的值。在后续调用中,resume的实参值将成为Fiber.yield的返回值。相反地,Fiber.yield的实参值将成为resume的返回值。当纤程的代码块结束时,最后一个被执行的表达式的值将成为resume的返回值。
  98. 方法是一个有名代码块,是与一个或多个对象相关联的参数化代码。调用方法时需要给出方法名、所在对象们,以及零个或多个与有名参数对应的参数值。方法中最后一个表达式的值将作为方法调用的返回值
  99. 闭包:它们会保持定义时所在范围内的局部变量,即在另外的范围内被调用时,它们也可以对这些变量进行访问。
  100. Return关键字在到达方法最后一个表达式前强行返回。如果一个表达式跟在return之后,它的值会作为方法返回值。如果return后面没有任何表达式,那么返回值为nil
  101. Ruby方法可以返回多个值,这需要显式使用return语句,并把要返回的值用逗号分隔开
  102. 方法永远是在一个对象上被调用的。在方法代码中,self代表方法被调用的对象。如果调用方法时不指定对象,这表示方法在self上被调用
  103. 只需在def关键字后加上一个求值结果为对象的表达式,在这个表达式之后需要一个句点符号和要定义的方法。这样定义的方法被称为单键方法
  104. Ruby提供了alias的关键字用于为已有方法定义一个新的名字
  105. 一个Ruby方法可以有两个名字,但是两个方法不能共享一个名字。
  106. 接受任意数目参数的方法:需要在某个参数之前加上一个*符号
  107. 在方法调用时,如果在一个Proc对象前使用&,在这个调用中,就会像对一个普通代码块一样处理该Proc对象
  108. 如果在方法调用中使用&,它必须被用于修饰方法的最后一个参数。代码块可以与任何方法调用关联起来,即使这个方法并不需要一个代码块,而且也没有yield语句。任何方法调用都可以用一个&参数作为最后一个参数
  109. Proc类定义了==方法来判定两个Proc对象是否相等。记住两个proc或lambda拥有同样的代码并不意味着它们是相等的。只有当一个Proc对象是另一个Proc对象的克隆或复制品时,==方法才返回true
  110. 在类的代码体中(但是在任何实例方法定义体外),self关键字表示定义的类
  111. 类的最后一个表达式都是一个用于定义方法的def语句,def语句的值总是等于nil
  112. 实例方法是在一个类的实例上进行调用的方法。当一个实例方法被调用时,self的值就是该方法定义所在类的一个实例
  113. 类对象的new方法在创建一个实例后,自动调用该实例的initialize方法,传给new方法的所有参数被传递给initialize方法
  114. 任何自定义的类都应该定义一个to_s实例方法,用来返回代表该对象的字符串
  115. 类变量对所有该类实例的方法都可见,也对类定义本身可见。类变量名以@@打头
  116. 如果一个继承自抽象类的类实现了祖先类中所有的抽象方法,它就是一个具体类
  117. 私有方法不能在所定义的类外被调用,但是它们会被子类继承,这意味着子类可以调用它们,也可以覆盖它们。
  118. 每个类都继承了new这个类方法。这个方法要进行两项工作:它必须分配一个新对象,即让这个对象存在,并初始化这个对象。这两项工作,分别交给allocate和initialize方法来实现。
  119. Allocate是Class类的一个实例方法,被所有类对象继承,它的作用在于创建类的一个实例。你可以用这个方法创建一个未初始化的实例。不过不要试图覆盖它。Ruby总是忽略那些覆盖的版本,而直接调用原始版本。
  120. 产生新对象的方法是使用dup和clone方法,这些方法分配一个调用者所属类的实例,然后把调用者的所有实例变量及修改都拷贝到新创建的对象中。Clone比dup的拷贝动作更彻底,它还拷贝调用者的单键方法,如果调用者处在冻结状态,那么这个状态也被拷贝到新创建的对象中
  121. 单键是指仅仅拥有一个实例的类。在面向对象框架中,单键经常用于存储全局程序状态,它可以用来替代类方法和类变量
  122. 模块也是方法、常量和类变量的命名组,不过与类不同,模块不能被实例化,也不能被子类化。
  123. Ruby的加载路径是一个数组,可以通过全局变量$LOAD_PATH或$:进行访问。数组的每个元素都是一个目录名,Ruby在这些目录中查找加载路径,前面的目录比后面的目录优先被查找。
  124. 当Ruby为一个方法调用表达式求值时,它首先必须找出哪个方法被调用,这个过程被称为方法查找。
  125. 反射表示一个程序可以审视自身的状态和结果
  126. 元编程可以被粗略定义为用程序帮助你写程序
  127. 类和模块分别是类Class和Module的实例
  128. 如果把动态创建的匿名模块或类赋给一个常量,常量的名字就成为这个模块或类的名字
  129. 如果程序可以生成一个有效Ruby代码的字符串,就可以用Kernal.eval方法对它进行求值
  130. 一个Bind对象代表某一时刻Ruby变量的绑定状态,Kernal.binding返回调用时实际发生的绑定。可以把一个Binding对象作为第二个参数传给eval方法,那么指定的字符串将在这些绑定的上下文中被求值
  131. __FILE__和__FILE__表示文件名及代码所出现的行号
  132. 集合就是一组无重复值的集合。集合中的元素没有顺序
  133. 列举目录内容最简单的方式就是用Dir.entries方法或Dir.foreach迭代器
  134. 每个流可以有两个关联的编码方式,分别是外部编码和内部编码。分别可以通过IO对象的external_encoding和internal_encoding方法获得。外部编码是指存储在文件中的文本的编码方式,内部编码是指在Ruby中用于表示文本的编码方式
  135. 在流处于EOF状态时,gets方法返回nil,而readline则抛出一个EOFError异常。如果不知道流有多少行,用gets;如果知道那里应该还有一行,用readline,可以用eof?方法来检测一个流是否处在EOF状态。
  136. IO.read方法读取整个文件(或部分文件)到一个字符串中;IO.readlines读取文件到一个文本行数组中;IO.foreach方法迭代文件的每一行。所有这些方法都无须初始化一个IO对象
  137. 新线程可以通过Thread.new方法创建,创建线程后无须启动它,它将在CPU资源可用时自动启动。调用Thread.new会得到一个Thread对象,线程将允许Thread.new关联代码块中的代码,在运行完后停止。代码块中最后一条语句的值成为线程的值。它可以通过Thread对象的value方法获得。如果一个线程已经运行完成,那么这个值被立刻传给thread的value方法;否则,value方法被阻塞,直到线程完成。
  138. 类方法Thread.current返回代表当前线程的Thread对象。类方法Thread.main返回代表主线程的Thread对象—这是Ruby程序启动时的初始线程。
  139. Thread.list方法返回所有活跃线程(运行或休眠)的Thread对象数组。当一个线程结束时,它从这个数组中被删除。
  140.  

 

posted @ 2013-04-02 21:28  小楼  阅读(778)  评论(0编辑  收藏  举报