new、initialize 和 allocate¶
您可以透過在類別上呼叫 new
來建立該類別的實例
person = Person.new
在這裡,person
是 Person
的一個實例。
我們無法用 person
做太多事情,因此讓我們為它新增一些概念。一個 Person
有一個名稱和年齡。在「萬物皆物件」章節中,我們說一個物件有一個型別並回應某些方法,這是與物件互動的唯一方式,因此我們需要 name
和 age
方法。我們將把這些資訊儲存在實例變數中,這些變數總是以前綴符號 at (@
) 字元開頭。我們也希望 Person
在產生時具有我們選擇的名稱和零的年齡。我們使用一個特殊的 initialize
方法來編碼「產生」的部分,這個方法通常被稱為建構子
class Person
def initialize(name : String)
@name = name
@age = 0
end
def name
@name
end
def age
@age
end
end
現在我們可以這樣建立人員
john = Person.new "John"
peter = Person.new "Peter"
john.name # => "John"
john.age # => 0
peter.name # => "Peter"
(如果您想知道為什麼我們需要指定 name
是 String
,但不需要對 age
這麼做,請查看全域型別推論演算法)
請注意,我們使用 new
建立 Person
,但我們在 initialize
方法中定義了初始化,而不是在 new
方法中。為什麼會這樣呢?
答案是,當我們定義 initialize
方法時,Crystal 會為我們定義一個 new
方法,就像這樣
class Person
def self.new(name : String)
instance = Person.allocate
instance.initialize(name)
instance
end
end
首先,請注意 self.new
標記法。這是一個類別方法,屬於 Person
類別,而不是該類別的特定實例。這就是為什麼我們可以執行 Person.new
。
其次,allocate
是一個低階類別方法,會建立給定型別的未初始化物件。它基本上會為物件配置必要的記憶體,然後在其上呼叫 initialize
,最後傳回實例。您通常永遠不會呼叫 allocate
,因為它是不安全的,但這就是 new
和 initialize
相關的原因。