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
之间关系的原因。