1.理解Ruby中的true

2.所有对象的值都可能是nil

3.避免使用ruby中存在的古怪的perl风格语法

4.注意常量是可变的

5.留意运行时警告

1.理解Ruby中的true

#1.除了false和nil之外的所有值都表示为真值

#2.使用nil?来判断是否为nil
nil.nil? #=>true
false.nil? #=>false

#使用比较时,false需要放在“==”表达式的左边,因为“==”是BasicObject的方法,能被普通类继承和改写
class Bad
  def ==(other)
    true
  end
end

false == Bad.new #=>false
Bad.new == false #=>true,Bad.new和false相当于调用了“==”方法

#3.true、false、nil都是其单例的唯一实例化对象,可以直接调用其实例方法
true.class #TrueClass
false.class #FalseClass
nil.class #NilClass

2.所有对象的值都可能是nil

#开发中常见的问题
undefined method "xx" for nil:NilClass(NoMethodError)

#通过下面的几种方式来排除nil, 判断,转换和去除

#判断 nil?方法
person.save if person
person.save if !person.nil?
person.save unless person.nil?

#转换 将对象转换为期望的类型
nil.to_s #=> " "
nil.to_a #=> []
nil.to_i #=> 0
nil.to_f #=> 0.0

#去除 Array#compact方法返回去掉所有nil元素的方法的接受者的副本
name = [first, middle, last].compact.join(" ")

3.避免使用ruby中存在的古怪的perl风格语法

#1.使用String#match替代String#=~,前者将匹配信息以MatchData对象返回
def extract_error(message)
  if message =~ /^ERROR:\s+(.+)$/
    $1
  else
    "no error"
  end  
end

def extract_error(message)
  if m = message.match(/^ERROR:\s+(.+)$/)
    m[1]
  else
    "no error"
  end  
end

#2.使用更长,更表意的全局变量的别名,比如使用$LOAD_PATH代替$:

#3.避免使用隐式读写全局变量$_的方法(不懂,备注)
while readline
  print if ~ /^ERROR:/
end

4.注意常量是可变的

#ruby中的常量是可变的,如果改变常量会出现警告,但是还是会改变成功
Demo = "demo"
Demo = "hello" #warning: already initialized constant Demo

#对单个常量执行freeze, 进行赋值的过程中也会成功
Demo = "demo"
Demo.freeze
Demo = "hello" #warning: already initialized constant Demo

#对于在moduel中的常量,可以通过freeze这个module来冻结常量,使得其不能被改变
module Defaults
  TIMEOUT = 5
end
Defaults.freeze
Defaults::TIMEOUT = 10  #出现错误

#对数组进行freeze是进行浅冻结,这样子不可以增减元素,但是可以改变元素
array = ["a", "b"]
array.freeze
array << "c"  #失败,因为该数组进行了freeze
array.each{|obj| obj << "c"} #成功,值为["ac", "bc"],说明值并没有进行freeze

#对数组和数组中的元素都进行freeze,可以达到如上完全freeze数组的目的
array.each(&:freeze).freeze #对数组进行freeze的同时对数组内的元素freeze
array.each{|obj| obj << "c"} #失败

5.留意运行时警告

ruby -w script.rb

results matching ""

    No results matching ""