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

newRuby では、「 」と「 」の関係は何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

ただし、もちろん、それをオーバーライドして、必要なことを行うことができます。

初期化中に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 にはメソッドしかなく、値を返すことができます。

あなたが見ている問題は、あるメソッドの戻り値を変更したいのに、別のメソッドをオーバーライドしていることです。method の戻り値を変更したい場合は、他のメソッドではなく、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

2 つの方法には重要な違いがあります。

newクラスメソッドであり、通常はクラスのインスタンスを作成します (これは、Ruby によって保護されているメモリの割り当てなどのトリッキーな処理を処理するため、あまり手を加える必要はありません)。

次に、initializeインスタンスメソッドである が、要求されたパラメータに従って内部状態を設定するようにオブジェクトに指示します。

必要に応じて、これらのいずれかをオーバーライドできます。たとえば、それを行うのに十分なほど賢くする必要がある場合Foo.newは、実際に のインスタンスを作成して返す場合があります。FooSubclass

ただし、多くの場合、これらのようなユース ケースは、たとえばFoo.relating_to(bar). メソッド like が何をnewすべきかについて他の人々の期待を裏切ることは、長期的には彼らを助けるよりも混乱させるでしょう.

Singleton例として、特定のクラスのインスタンスを 1 つだけ存在させるモジュールであるの実装を見てください。メソッドをプライベートにし、オブジェクトの既存のインスタンスを返すか、まだ作成されていない場合は呼び出すメソッドをnew公開します。instancenew

于 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のオブジェクトが必要な場合、なぜreturn nilFoo.new(1)を期待return nilするのでしょうか?Foo.new(0)

于 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 に答える