在Ruby中,'new'和'initialize'之间的关系是什么?初始化时如何返回nil?

时间:2012-04-30 12:14:13

标签: ruby constructor return new-operator initializer

我想要的是:

obj = Foo.new(0)  # => nil or false

这不起作用:

class Foo
  def initialize(val)
    return nil if val == 0
  end
end

我知道在C / C ++ / Java / C#中,我们无法在构造函数中返回一个值。

但我想知道Ruby是否可行。

5 个答案:

答案 0 :(得分:78)

  

在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中没有构造函数这样的东西。在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),你想要回来的是什么?您想要42Foo#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>

不同计算机的输出会有所不同。