我想要的是:
obj = Foo.new(0) # => nil or false
这不起作用:
class Foo
def initialize(val)
return nil if val == 0
end
end
我知道在C / C ++ / Java / C#中,我们无法在构造函数中返回一个值。
但我想知道Ruby是否可行。
答案 0 :(得分:78)
在Ruby中,“
new
”与“initialize
”之间的关系是什么?
new
通常会调用initialize
。 new
的默认实现类似于:
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
# actually, this is obj.send(:initialize, …) because initialize is private
obj
end
end
但是,当然,你可以覆盖它来做你想做的任何事情。
初始化时如何返回nil?
我想要的是:
obj = Foo.new(0) # => nil or false
这不起作用:
class Foo def initialize(val) return nil if val == 0 end end
我知道在C / C ++ / Java / C#中,我们无法在构造函数中返回一个值。
但我想知道Ruby是否可行。
Ruby中没有构造函数这样的东西。在Ruby中,只有方法,它们可以返回值。
您看到的问题只是您想要更改一个方法的返回值,但是您要覆盖其他方法。如果您想更改方法bar
的返回值,则应覆盖bar
,而不是其他方法。
如果您想更改Foo::new
的行为,则应更改Foo::new
:
class Foo
def self.new(val)
return nil if val.zero?
super
end
end
但请注意,这是非常糟糕的主意,因为它违反了new
的合同,即返回完全初始化的,完全正常运行的类实例。< / p>
答案 1 :(得分:45)
这两种方法之间存在重要差异。
new
是一个类方法,它通常会创建一个类的实例(这会处理一些棘手的事情,例如分配Ruby保护你的内存,所以你不必太脏了。)
然后,initialize
,一个实例方法,告诉对象根据请求的参数设置其内部状态。
根据您的需要,可以覆盖其中任何一个。例如,Foo.new
实际上可能会创建并返回FooSubclass
的实例,如果它需要足够聪明的话。
但是,通常最好将这些用例委托给其他类方法,这些方法更明确地说明了它们的作用,例如Foo.relating_to(bar)
。打破其他人对于new
这样的方法应该做什么的期望会让人们感到困惑,从长远来看,这会让他们感到困惑。
作为示例,请查看Singleton
的实现,这是一个只允许特定类的一个实例存在的模块。它使new
方法变为私有,并公开instance
方法,该方法返回对象的现有实例,或者如果尚未创建则调用new
。
答案 2 :(得分:5)
你可以这样:
class Foo
def self.init(val)
new(val) unless val == 0
end
def initialize(val)
#...
end
end
使用示例:
obj = Foo.init(0)
=> nil
obj = Foo.init(5)
=> #<Foo:0x00000002970a98>
答案 3 :(得分:4)
想要做
class Foo
def initialize(val)
return nil if val == 0
end
end
会导致代码不一致。
如果你有
class Foo
def initialize(val)
return nil if val == 0
@val = val
@bar = 42
end
end
如果你做Foo.new(1)
,你想要回来的是什么?您想要42
(Foo#initialize
的返回值)还是foo
对象?如果您想要foo
Foo.new(1)
对象,那么为什么return nil
期望Foo.new(0)
返回nil?
答案 4 :(得分:-1)
只需创建一个像这样的对象变量即可解决:
class Foo
def initialize(val)
@val = val
return nil if @val == 0
end
end
obj = Foo.new(0)
Output:-
=>#<Foo:0x1243b8 @val=0>
不同计算机的输出会有所不同。