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

Chr*_*Xue 48 ruby constructor return initializer new-operator

我想要的是:

obj = Foo.new(0)  # => nil or false
Run Code Online (Sandbox Code Playgroud)

这不起作用:

class Foo
  def initialize(val)
    return nil if val == 0
  end
end
Run Code Online (Sandbox Code Playgroud)

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

但我想知道Ruby是否可行.

Jör*_*tag 79

在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
Run Code Online (Sandbox Code Playgroud)

但是,当然,你可以覆盖它来做你想做的任何事情.

初始化时如何返回nil?

我想要的是:

obj = Foo.new(0)  # => nil or false
Run Code Online (Sandbox Code Playgroud)

这不起作用:

class Foo
  def initialize(val)
    return nil if val == 0
  end
end
Run Code Online (Sandbox Code Playgroud)

我知道在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
Run Code Online (Sandbox Code Playgroud)

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

  • `self`*在那里是*`Foo`.尝试`class Foo; p self end#=> Foo` (3认同)

Gar*_*eth 45

这两种方法之间存在重要差异.

new是一个方法,它通常创建一个类的实例(这涉及棘手的东西,如分配Ruby保护你的内存,所以你不必太脏).

然后,initialize中,实例方法,讲述了根据所要求的参数来设置其内部状态的目标对象.

根据您的需要,可以覆盖其中任何一个.例如,Foo.new实际上可能创建并返回一个实例,FooSubclass如果它需要足够聪明来做到这一点.

但是,通常最好将这些用例委托给其他类方法,例如,这些方法更明确地说明了它们的作用Foo.relating_to(bar).打破其他人对于new应该做什么方法的期望会让人们感到困惑,从长远来看,这对他们有所帮助.

作为示例,请查看Singleton一个模块的实现,该模块仅允许特定类的一个实例存在.它使该new方法变为私有,并公开一个instance方法,该方法既返回对象的现有实例,也调用new尚未创建的方法.


Fle*_*oid 5

你可以这样:

class Foo

  def self.init(val)
    new(val) unless val == 0
  end

  def initialize(val)
    #...
  end
end
Run Code Online (Sandbox Code Playgroud)

用法示例:

obj = Foo.init(0)
 => nil
obj = Foo.init(5)
 => #<Foo:0x00000002970a98>
Run Code Online (Sandbox Code Playgroud)


And*_*imm 5

想做

class Foo
  def initialize(val)
    return nil if val == 0
  end
end
Run Code Online (Sandbox Code Playgroud)

会导致代码不一致。

如果你有

class Foo
  def initialize(val)
    return nil if val == 0
    @val = val
    @bar = 42
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你这样做了,你想得到什么Foo.new(1)?你想要42( 的返回值Foo#initialize),还是一个foo对象?如果你想foo为对象Foo.new(1),那么为什么你会希望return nilFoo.new(0)回零?