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_accessor
、attr_writer
、attr_reader
類別方法可以直接定義這些方法。上述的程式可以改寫成:
class Person
attr_accessor :name
end
p = Person.new('ihower')
p.name
=> "ihower"
p.name="peny"
=> "peny"
這裡的attr_accessor
其實就是一個類別方法。
Ruby的private和protected定義和其他程式語言不同,都是可以在整個繼承體系內呼叫。兩著差別在於private只有不指定接受者(receiver)時才可以呼叫,你甚至不能打self.private_method_1
,預設一定就是self當成private方法的接受者。而protected方法除了可以被一個類別或子類別的物件呼叫,也可以讓另一個相同類別的物件來當做接受者。
在物件導向的術語中,
object.call_method
的意思是object收到執行call_method的指令,也就是object是call_method方法的接受者(receiver)。因此,你甚至可以改寫成object.__send__(:call_method)
Module是Ruby一個非常好用的功能,它跟Class類別非常相似,你會在裡面定義方法。只是你不能用new來建立它。它的第一個用途是可以當做Namespace來放一些工具方法:
module MyUtil
def self.foobar
puts "foobar"
end
end
MyUtil.foobar
# 輸出 foobar
另一個更重要的功能是Mixins,可以將一個Module混入類別之中,這樣這個類別就會擁有此Module的方法。這回讓我們拆成兩個檔案,debug.rb和foobar.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
如果result
是nil
的話,將a
指派給result
。以上這段程式等同於
result = a if result.nil?