在Ruby中,“新”和“初始化”之间有什么关系? 初始化时如何返回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中,“ new ”和“ initialize ”之间有什么关系?

new通常会调用initializenew的默认实现是这样的:

 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中没有这样的构造函数 。 构造函数在devise良好的语言中是不必要的。 在Ruby中,只有方法,当然方法可以返回值。

你所看到的问题只是你想改变一个方法的返回值,但是你正在重写一个不同的方法。 当然 ,这是行不通的。 如果你想改变方法bar的返回值,你应该重写bar ,而不是其他方法。

如果你想改变Foo::new的行为,那么你应该改变Foo::new

 class Foo def self.new(val) return nil if val.zero? super end end 

但是请注意,这是一个非常糟糕的主意 ,因为它违反了new的合同,即返回一个完全初始化的,完全正常运行的类实例。

这两种方法之间有重要的区别。

new是一个方法,它通常创build一个类的实例(它处理棘手的事情,比如分配Ruby所保护的内存,所以你不必太脏)。

然后, initialize一个实例方法,告诉对象根据请求的参数设置其内部状态。

这些都可以取决于你想要的。 例如, Foo.new实际上可能创build并返回一个FooSubclass的实例,如果它需要足够聪明的话。

但是,通常最好将这些用例委派给其他更明确的类方法,比如Foo.relating_to(bar) 。 打破别人对new方法应该做的方法的期望会让人们感到困惑,而不是从长远来看帮助他们。

作为一个例子,看一下Singleton的实现,这个模块只允许一个特定类的一个实例存在。 它使new方法变为private,并公开一个instance方法,该方法返回该对象的现有实例,或者在尚未创build的情况下调用new

你可以这样:

 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> 

想要做

 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)你想要得到什么? 你想要42Foo#initialize的返回值)还是foo对象? 如果你想为Foo.new(1)一个foo对象,那么为什么你会期望return nil来使Foo.new(0)返回nil?

Ruby中的类是第一类对象 – 每个类都是类Class的一个实例。 当定义一个新的类(通常使用类名称…结束)时,会创build一个Classtypes的对象,并将其分配给一个常量(在本例中为Name)。 当调用Name.new来创build一个新的对象时,默认运行Class中新的类方法,然后调用allocate为对象分配内存,然后调用新对象的initialize方法。 一个对象的构build和初始化阶段是分开的,都可以被覆盖。 构造是通过新的类方法完成的,初始化是通过初始化实例方法完成的。 初始化不是一个构造函数!

这是通过简单地创build一个像这样的对象variables来解决的:

 class Foo def initialize(val) @val = val return nil if @val == 0 end end obj = Foo.new(0) Output:- =>#<Foo:0x1243b8 @val=0> 

输出在不同的电脑上有所不同。