Ruby 基础教程第4版读书笔记 1

Ruby 初体验

  • print("Hello, \nRuby!") 程序会对双引号里 \ 后的字符进行转义,而单引号中的则不会。
  • puts "Hello, ", "Ruby!" 当参数为两个字符串的时候,各字符串末尾都会加上换行符。
  • 使用 p 方法,打印出的数值结果和字符串结果会以不同的形式输出。另外其中的转移符不会转义。
  • Ruby 2 开始默认编码使用 UTF-8 编码方式,如果输出中文有乱码的话,可以用 -E 指定输出结果的编码方式。
ruby -E UTF-8 hello.rb
irb -E UTF-8
  • irb 命令后的选项 –simple-prompt 会简化 irb 的输出结果。
  • 利用 Math 模块进行的数学运算的返回结果是科学计数法 9.26535896604902e-05
  • --begin=end 中间的部分也是注释。
  • while 语句可以省略后面的 do
  • 正则表达式可以简单的实现:
    • 将字符串和模式 pattern 相匹配
    • 使用模式分割字符串
  • 利用运算符 =~ 来匹配模式和字符串。若匹配成功则返回匹配部分的位置,否则返回 nil。
  • 使用 ARGV 这个数组来获取从命令行传递过来的数据。从这里得到的数据都是字符串。
  • 一下子读取全部数据很消耗内容,改成 File.each_line 就很好了。
  • Regexp.new(str) 表示把字符串转换成正则表达式对象。
pattern = Regexp.new(ARGV[0])
filenmae = ARGV[1]

file = File.open(filename)
file.each_line do |line|
  if pattern =~ line
    puts line
  end
end
file.close
  • 引用 pp 库之后的 pp 方法可以打印出更好的对象。
  • 库与脚本放在同一文件夹时,需要用 ./ 来表示文件存放在当前目录。

Ruby 的基础

并行赋值

a = 1; b = 2; c = 3
a, b, c = 1, 2, 3
  • 左右两边数量不相等,也不报错。左边数量较多时,会自动将 nil 赋值给未分配值的变量。
a, b, c, d = 1, 2
p [a, b, c] #=> [1, 2, nil]
  • 变量部分较少时,会自动忽略该值,不会分配多余的值。
a, b, c = 1, 2, 3, 4
p [a, b, c] #=> [1, 2, 3]
  • 变量前加上 * 表示会将未分配的值封装为数组赋值给该变量。
a, b, *c = 1, 2, 3, 4, 5
p [a, b, c] #=> [1, 2, [3, 4, 5]]
a, *b, c = 1, 2, 3, 4, 5
p [a, b, c] #=> [1, [2, 3, 4], 5]
  • 置换变量的值
a, b = b, a
  • 用数组赋值,左边有多个变量时,会自动获取数组的元素进行多重赋值。
ary = [1, 2]
a, b = ary
p a #=> 1
p b #=> 2

a, = ary
p a #=> 1
  • 获取嵌套数组的元素
ary = [1, [2, 3], 4]
a, b, c = ary
p a #=> 1
p b #=> [2, 3]
p c #=> 4

a, (b1, b2), c = ary
p a #=> 1
p b1 #=> 2
p b2 #=> 3
p c #=> 4

条件与真假值

  • 不返回 true 或 false 的方法只要能返回 nil,也可以作为条件判断的表达式来使用。
  • 为了便于程序理解,返回真假值的方法都要以 ? 结尾。

=== 与 case 语句

  • case 中的 when 实际是使用 === 运算符来判断
  • 在判断字符串相等的时候 ===== 意义一样
  • === 还可以与 =~ 一样用来判断正则表达式是否匹配
  • 判断右边的对象是否属于左边的类

对象的一致性

  • equal? 方法判断两个对象是否是同一个对象(ID是否相同)

循环

循环时的注意事项

  1. 循环的主体是什么
  2. 停止循环的条件是什么

循环控制

命令 用途
break 终止程序,跳出循环
next 跳到下一次循环
redo 在相同条件下不断重复刚才的处理。容易陷入死循环,慎用。

总结

命令 用途
times 确定循环次数时使用
for 从对象取出元素时使用(建议用 each)
while 希望自由指定循环条件时时候
until 使用 while 语句使循环条件变得难懂时使用
each 从对象取出元素时使用
loop 不限制循环次数时使用

方法

  • 调用类方法时可以使用 :: 例如 Array.new 等同于 Array::new
  • 方法的目的是程序处理,所以允许没有返回值的方法,更准确的说允许返回值是 nil
  • 调用方法时通过块传递进来的处理会在 yield 定义的地方执行

一些基础知识

  • 想知道对象属于某个类,可以使用 class 方法,判断某个对象属于某个类,可以使用 instance_of? 方法。
  • 根据类的继承关系反向追查对象是否属于某个类时,可用 is_a? 方法。
  • 我们把通过扩展已定义的类来创建新类成为继承。
    • 在不影响原有功能的前提下追加新功能。
    • 重定义原有功能,使名称相同的方法产生不同的效果。
    • 在已有功能的基础上追加处理,扩展已有功能。
  • BasicObject 类是 Ruby 中所有类的父类,定义了 Ruby 对象的最基本功能。
  • 定义类时没有指定父类的话,默认该类的为 Object 的子类。
  • 使用 new 方法生成新的对象时,会自动调用 initialize 方法。
  • 类调用 instance_methods 会以符号形式返回类的实例方法列表。

类的实例及其方法

  • 在同一个实例中,程序可以超越方法定义,任意引用,修改实例变量的值。引用未初始化的实例变量时返回值为 nil
  • 从外部对象不能直接访问实例变量,或对实例变量赋值,需要通过方法来访问对象内部。
  • 在实例方法中,可以用 self 这个特殊的变量来引用方法的接收者。
  • 省略接收者,默认会把 self 作为该方法的接收者。
  • 即使对 self 赋值也不生效。

类方法

there are some ways about how to define class method.

class << HelloWorld
  def hello(name)
    puts "#{name} said hello."
  end
end

class HelloWorld
  class << self
    def hello(name)
      puts "#{name} said hello."
    end
  end
end

class HelloWorld
  def self.hello(name)
    puts "#{name} said hello."
  end
end
  • public 以实例方法的形式向外部公开该方法。
  • private 在指定接收者的情况下无法调用该方法,也表示只能使用缺省接收者的方式调用该方法,因此无法从实例外部访问。
  • protected 在同一个类及其子类中时可将该方法作为实例方法调用。

其它

  • alias 别名 原名 或者 alias :别名 :原名
  • 重定义已存在的方法时,为了能用别名调用原来的方法,我们会用到 alias 方法
  • undef 方法名 或者 undef :方法名
  • extend 方法可以使单例类包含模块,并把模块的功能扩展到对象中。
  • include 帮助我们突破继承的限制,通过模块扩展类的功能。extend 帮助我们跨过类,直接通过模块扩展对象的功能。
module Edition
  def edition(n)
    "#{self}#{n}版"
  end
end

str = "Ruby 教材"
str.extend(Edition)
puts str.edition(4)
  • extend 也同样能为类对象追加类方法。
module ClassMethods
  def cmethod
  end
end

module InstanceMethods
  def imethod
  end
end

class MyClass
  extend ClassMethods
  include InstanceMethods
end

MyClass.cmethod
MyClass.new.imethod

模块

  • 类表现的是事物的数据和行为,模块只表现行为部分。
  • 命名空间可以对方法,常量,类等名称进行区分及管理。
  • module_function :hello 定义模块函数。
  • 使用 模块名.方法名 的形式来调用在模块中定义的方法,这样的方法成为模块函数。
  • include 方法可以把模块内的方法,常量合并进入当前的命名空间。
  • 如果没定义与模块内的方法,常量同样的名称,就可以省略模块名,直接调用。
  • 不建议在定义为模块函数的方法内部使用 self
  • 想知道类是否包含某个模块,可以使用 include? 方法,ancestors 取得继承关系的列表。

面向对象编程

  • 对象之间通过方法交换信息,不关心彼此内部是如何处理的。
  • 封装指对象管理的数据不能直接从外部进行操作,数据的更新,查询等操作必须通过调用对象的方法来完成。
  • 多态指各个对象都有自己独有的消息解释权。一个方法名属于多个对象,不同对象的处理结果不一样。
  • 鸭子类型是指对象的特征不是由其类及其类的继承关系来决定的,而是由对象本身具有什么样的方法决定的。

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @Victor Nov 4, 2014

奉献爱心