56

我想要的是:

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

这不起作用:

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

我知道在 C/C++/Java/C# 中,我们不能在构造函数中返回值。

但我想知道在 Ruby 中是否有可能。

4

5 回答 5

86

new在 Ruby 中,' ' 和 ' '之间是什么关系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

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

初始化时如何返回零?

我想要的是:

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,即返回一个完全初始化的、功能齐全的类实例。

于 2012-04-30T12:45:56.127 回答
48

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

new是一个方法,它通常创建一个类的实例(它处理一些棘手的事情,比如分配内存,Ruby 会保护你,这样你就不必太脏了)。

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

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

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

举个例子,看看 的实现Singleton,一个只允许特定类的一个实例存在的模块。它使该new方法成为私有方法,并公开一个instance方法,该方法要么返回对象的现有实例,要么new在尚未创建时调用。

于 2012-04-30T12:33:58.903 回答
8

你可以这样:

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>
于 2012-04-30T12:22:41.550 回答
5

想做

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对象 for Foo.new(1),那么你为什么要return nil返回Foo.new(0)nil 呢?

于 2012-04-30T23:22:10.283 回答
-2

它可以通过简单地创建一个对象变量来解决,如下所示:

class Foo
   def initialize(val)
       @val = val
       return nil if @val == 0
   end
end
obj = Foo.new(0)

Output:-
=>#<Foo:0x1243b8 @val=0>

输出在不同的计算机中有所不同。

于 2014-05-30T09:41:34.360 回答