大家對於方法的定義和使用大致理解後,今天想跟大家聊聊ruby內特別的方法,大家有印象我在前兩天的舉例都會在類別內定義一個initialize
方法以及attribute accessor
嗎?
initialize
顧名思義就是初始化,他是一個特殊的構造方法(constructor method)
,是Ruby在建立物件(object)
過程中的一個環節。Ruby允許我們在建立物件時執行一些初始化的操作,也就是說當你new
出一個物件時,initialize
方法會自動被調用,藉由initialize
賦予物件初始的值、行為或狀態。
class Person
def initialize(name, age)
@name = name
@age = age
end
def introduce
puts "Hi, I'm #{@name}, and I'm #{@age} years old."
end
end
# 建立 Person 實體時,自動調用 initialize 方法
amanda = Person.new("Amanda", 28) #<Person:0x0000555e7b1ba0b0 @name=Amanda, @age=28>
# 調用對象的方法
puts amanda.introduce # "Hi, I'm Amanda, and I'm 28 years old."
更進一步,我們希望person
物件在建立時都帶有初始值,那我們可以使用運算符or(’||’)
來提供默認值,如果傳遞給建構方法的參數age
是nil
(即沒有傳遞參數),統一都會是18
。
class Person
def initialize(name, age)
@name = name
@age = age ||= 18
end
end
# 建立 Person 實體時,自動調用 initialize 方法
amanda = Person.new("Amanda", 28) #<Person:0x0000555e7b1ba0b0 @name="Amanda", @age=28>
lilith = Person.new("Lilith") #<Person:0x0000534i7e2ca1a0 @name=Amanda, @age=18>
Ruby 並沒有定義「屬性」,因此,當我們直接取用實體變數時,會出現錯誤:
class Person
def initialize(name, age)
@name = name
@age = age
end
end
# 建立 Person 實體時,自動調用 initialize 方法
amanda = Person.new("Amanda", 28)
amanda.name # NoMethodError: undefined method 'name'
需要另外定義方法,因為只有方法可以取用實體變數。
class Person
def initialize(name, age)
@name = name
@age = age
end
def introduce
puts "Hi, I'm #{@name}, and I'm #{@age} years old."
end
def name
@name
end
def name=(value)
@name = value
end
end
# 建立 Person 實體時,自動調用 initialize 方法
amanda = Person.new("Amanda", 28)
amanda.name = "New Amanda"
puts amanda.name # "New Amanda"
為了解決這個問題,Ruby 有幫我們定義了1個方法:attr_accessor
,讓我們可以更輕鬆的來取用實體變數
class Person
attr_accessor :name
# 替我們建立 name, name=
def initialize(name, age)
@name = name
@age = age
end
def introduce
puts "Hi, I'm #{@name}, and I'm #{@age} years old."
end
#def name
#@name
#end
#def name=(value)
#@name = value
#end
end
# 建立 Person 實體時,自動調用 initialize 方法
amanda = Person.new("Amanda", 28)
puts amanda.name # "Amanda"
除了attr_accessor
還有 attr_reader
和attr_writer
,相較於attr_accessor
可以一次創建getter和setter,attr_reader
只有讀取實體變數的功能,不能改變資料,需要搭配attr_writer
才能改變資料。
我的理解是把initialize
和attribute accessors
作為建立一個新類別時的起手式,可以在定義類別時先建立好需要的資料,某種程度上也是類別藍圖的一部分,明確的知道他帶有哪些行為或狀態,並且能彈性的取用和修改行為或狀態。
參考資料: