跳至内容

new、初始化和分配

通过在类上调用 new 来创建类的实例

person = Person.new

这里,personPerson 的一个实例。

我们无法对 person 做太多操作,所以让我们添加一些概念到它。一个 Person 有一个姓名和一个年龄。在“万物皆对象”一节中,我们说一个对象具有一个类型并响应某些方法,这是与对象交互的唯一方式,因此我们需要 nameage 方法。我们将把这些信息存储在实例变量中,这些变量总是以 at (@) 字符为前缀。我们还希望一个人在出生时拥有我们选择的姓名和 0 岁的年龄。我们使用一个特殊的 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,因为它是不安全的,但这正是 newinitialize 之间关系的原因。