new、初始化和分配¶
通过在类上调用 new 来创建类的实例
person = Person.new
这里,person 是 Person 的一个实例。
我们无法对 person 做太多操作,所以让我们添加一些概念到它。一个 Person 有一个姓名和一个年龄。在“万物皆对象”一节中,我们说一个对象具有一个类型并响应某些方法,这是与对象交互的唯一方式,因此我们需要 name 和 age 方法。我们将把这些信息存储在实例变量中,这些变量总是以 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,因为它是不安全的,但这正是 new 和 initialize 之间关系的原因。