跳至內容

new、initialize 和 allocate

您可以透過在類別上呼叫 new 來建立該類別的實例

person = Person.new

在這裡,personPerson 的一個實例。

我們無法用 person 做太多事情,因此讓我們為它新增一些概念。一個 Person 有一個名稱和年齡。在「萬物皆物件」章節中,我們說一個物件有一個型別並回應某些方法,這是與物件互動的唯一方式,因此我們需要 nameage 方法。我們將把這些資訊儲存在實例變數中,這些變數總是以前綴符號 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"

(如果您想知道為什麼我們需要指定 nameString,但不需要對 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,因為它是不安全的,但這就是 newinitialize 相關的原因。