ruby 入门基础知识

常量:

ruby要求常量首字母要大写,但是为了可读性,建议全部大写 。而且, 说是常量, 却是可变的, 但是会有警告。

Range

比如,1..3 ,1...3,两个点包括末个数值3 ,三个点不包括3

to_s(轉成字串)、to_i(轉成整數)或to_f(轉成浮點數)

方法名稱可以用?!結尾,前者表示會回傳Boolean值,後者暗示會有某種副作用(side-effect)

資料封裝

所有的物件變數(@開頭)、類別變數(@@開頭),都是封裝在類別內部的,類別外無法存取:

class Person
    def initialize(name)
        @name = name
    end
end

p = Person.new('ihower')
p.name 
=> NoMethodError
p.name='peny' 
=> NoMethodError

為了可以存取到@name,我們必須定義方法:

class Person

   def initialize(name)
    @name = name
   end

   def name
     @name
   end

   def name=(name)
     @name = name
   end
end

p = Person.new('ihower')
p.name 
=> "ihower"
p.name="peny"
=> "peny"

上述定義物件變數的存取方法實在太常見了,因此Ruby提供了attr_accessorattr_writerattr_reader類別方法可以直接定義這些方法。上述的程式可以改寫成:

class Person
  attr_accessor :name
end

p = Person.new('ihower')
p.name 
=> "ihower"
p.name="peny"
=> "peny"    

這裡的attr_accessor其實就是一個類別方法。

Rubyprivateprotected定義和其他程式語言不同,都是可以在整個繼承體系內呼叫。兩著差別在於private只有不指定接受者(receiver)時才可以呼叫,你甚至不能打self.private_method_1,預設一定就是self當成private方法的接受者。而protected方法除了可以被一個類別或子類別的物件呼叫,也可以讓另一個相同類別的物件來當做接受者。

在物件導向的術語中,object.call_method的意思是object收到執行call_method的指令,也就是objectcall_method方法的接受者(receiver)。因此,你甚至可以改寫成object.__send__(:call_method)

ModuleRuby一個非常好用的功能,它跟Class類別非常相似,你會在裡面定義方法。只是你不能用new來建立它。它的第一個用途是可以當做Namespace來放一些工具方法:

module MyUtil

    def self.foobar
        puts "foobar"
    end
end

MyUtil.foobar
# 輸出 foobar

另一個更重要的功能是Mixins,可以將一個Module混入類別之中,這樣這個類別就會擁有此Module的方法。這回讓我們拆成兩個檔案,debug.rbfoobar.rb,然後在foobar.rb中用require來引用debug.rb

首先是debug.rb

module Debug
    def who_am_i?
        puts "#{self.class.name}: #{self.inspect}"
    end
end

然後是foobar.rb

require "./debug"
class Foo
    include Debug # 這個動作叫做 Mixin
end

class Bar
    include Debug
end

f = Foo.new
b = Bar.new
f.who_am_i? # 輸出 Foo: #<Foo:0x00000102829170>
b.who_am_i? # 輸出 Bar: #<Bar:0x00000102825b88>

Ruby使用Module來解決多重繼承的問題,不同類別之間但是擁有相同的方法,就可以改放在Module裡面,然後include它即可。

其他迭代方式範例

# 迭代並造出另一個陣列
a = [ "a", "b", "c", "d" ]
b = a.map {|x| x + "!" }
puts b.inspect

# 結果是 ["a!", "b!", "c!", "d!"]

# 找出符合條件的值
b = [1,2,3].find_all{ |x| x % 2 == 0 }
b.inspect
# 結果是 [2]

# 迭代並根據條件刪除
a = [51, 101, 256]
a.delete_if {|x| x >= 100 }
# 結果是 [51]

# 客製化排序
[2,1,3].sort! { |a, b| b <=> a }
# 結果是 [3, 2, 1]

# 計算總和
(5..10).inject {|sum, n| sum + n }

# 找出最長字串find the longest word
longest = ["cat", "sheep", "bear"].inject do |memo,word|
    ( memo.length > word.length )? memo : word
end

<=>是比較運算子,當兩個數字相等於回傳0,第一個數字較大時回傳1,反之回傳-1

其他常见惯例:

result ||= a

如果resultnil的話,將a指派給result。以上這段程式等同於

result = a if result.nil?