在Ruby中,在创建新类时,我们将定义构造函数方法,如下所示:
class Thing
def initialize
do_stuff
end
end
但是,当实际创建对象的实例时,我们发现自己没有在实例上调用initialize
而在类上调用new
。
在这种情况下,我们为什么不改为定义::new
?
class Thing
def self.new
do_stuff
end
end
::new
没有定义的场景是initalize
吗?这两者有什么不同吗?定义::new
会有效吗?或者只是def initialize
比def self.new
更短(不是)?
我认为必须有充分的理由来弥补这种差异。
答案 0 :(得分:11)
New为新对象分配空间并创建它。然后,它调用Objects initialize方法,使用分配的内存创建一个新的Object。通常,您要自定义的唯一部分是实际创建,并且很乐意将后台内存分配留给Object.new方法,因此您编写了一个初始化方法。引擎盖下的新功能看起来像这样(C中除外):
class Object
def self.new(*args, &block)
object = allocate
object.send(:initialize, *args, &block)
return object
end
end
因此,当您调用Object.new时,实际发生的是:
1)分配内存 2)调用对象初始化方法。
答案 1 :(得分:5)
提供对实例变量的访问。
实例变量(例如@value
)只能从实例访问,但不能从类方法中访问。这与Java之类的语言不同,其中私有实例变量具有类而不是实例范围,因此可以从静态构造函数访问。
class Thing
def initialize
@value = 42
end
end
class Thing
def self.new
# no way to set the value of @value !!!!!!!!
end
end
对于那些对Ruby历史感兴趣的人,具有实例私有实例变量的对象模型可以追溯到Smalltalk。你可以在现代的Smalltalk方言中找到相同的模式,例如Pharo,new
在Object
中实现,以调用self initialize
,以便子类可以轻松初始化实例变量。
答案 2 :(得分:3)
allocate
作为基元并且通常定义new
,那么您将始终必须执行常见操作,例如调用allocate
并在最后返回对象,这对于做。通过使用new
和initialize
,前者将包装后者,因此您只需要定义包装内容,而不是包装器。new
是一个类方法,所以当你定义它时,默认情况下你没有访问实例方法和实例变量,你需要依赖访问器。另一方面,initialize
是一个实例方法,因此使用实例变量和实例方法会更容易。