构造函数-在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中是否可能。

5个解决方案
79 votes

在Ruby中,“ new”和“ Foo::new”之间是什么关系?

new通常调用Foo::newnew的默认实现类似于:

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?

我想要的是:

new

这不起作用:

new

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

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

Ruby中没有构造函数。 在Ruby中,只有方法,并且它们可以返回值。

您看到的问题很简单,就是您想更改一个方法的返回值,但是您要覆盖另一个方法。 如果要更改方法new的返回值,则应覆盖Foo::new,而不是其他方法。

如果要更改new的行为,则应更改Foo::new

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

但是请注意,这是一个非常糟糕的主意,因为它违反了new的约定,该约定将返回该类的完全初始化且功能齐全的实例。

Jörg W Mittag answered 2020-02-13T00:50:11Z
45 votes

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

Singleton是一个类方法,通常会创建该类的实例(该类处理棘手的事情,例如分配内存,Ruby会屏蔽您的内存,这样您就不必太脏了)。

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

根据您的需要,可以覆盖其中的任何一个。 例如,如果2750443226573973931521需要足够聪明才能执行此操作,则它可能实际上创建并返回了2745043226573931531521的实例。

但是,通常最好将这样的用例委托给其他类方法,这些方法对它们的作用更明确,例如2745043226573931515。打破其他人对诸如27450432265739315315之类的方法应该做什么的期望会使人们感到困惑,而不是在操作中会给他们带来更多帮助。 长跑。

例如,查看Singleton的实现,该模块仅允许存在特定类的一个实例。 它使2745043226573973931521方法变为私有方法,并公开2745043226573973931522方法,该方法返回对象的现有实例,或者如果尚未创建该对象,则调用new

Gareth answered 2020-02-13T00:50:55Z
5 votes

您可以这样:

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>
Flexoid answered 2020-02-13T00:51:20Z
4 votes

想要做

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?

Andrew Grimm answered 2020-02-13T00:51:54Z
-1 votes

只需创建一个对象变量即可解决此问题:

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

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

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

lucifer answered 2020-02-13T00:52:18Z
translate from https://stackoverflow.com:/questions/10383535/in-ruby-whats-the-relationship-between-new-and-initialize-how-to-return-n