私が欲しいのは:
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では、「
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
ただし、もちろん、それをオーバーライドして、必要なことを行うことができます。
初期化中に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にはconstructorのようなものはありません。 Rubyにはメソッドのみがあり、値を返すことができます。
あなたが見ている問題は、単にあるメソッドの戻り値を変更したいのに、別のメソッドをオーバーライドしているということです。メソッドbar
の戻り値を変更する場合は、他のメソッドではなく、bar
をオーバーライドする必要があります。
Foo::new
の動作を変更する場合は、Foo::new
を変更する必要があります。
class Foo
def self.new(val)
return nil if val.zero?
super
end
end
ただし、これは本当に悪い考えであることに注意してください。これは、new
の規約に違反しているためです。
2つの方法には重要な違いがあります。
new
はclassメソッドで、通常はクラスのインスタンスを作成します(これは、Rubyだからあなたはあまり汚くする必要はありません)。
次に、インスタンスメソッドであるinitialize
は、要求されたパラメーターに従って内部状態を設定するようにオブジェクトに指示します。
これらのいずれかは、必要に応じてオーバーライドできます。たとえば、_Foo.new
_は、実際にFooSubclass
のインスタンスを作成して返すことがあります。
ただし、多くの場合、これらのようなユースケースを、Foo.relating_to(bar)
のように、それらが行うことについてより明示的な他のクラスメソッドに委任する方が適切です。 new
のようなメソッドが何をすべきかについて他の人々の期待を破ると、人々を長期的に助けるよりも混乱させることになります。
例として、特定のクラスのインスタンスを1つだけ存在させるモジュールであるSingleton
の実装を見てください。 new
メソッドをプライベートにし、オブジェクトの既存のインスタンスを返すinstance
メソッドを公開するか、まだ作成されていない場合はnew
を呼び出します。
次のようなことができます:
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>
やりたい
_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.new(1)
のfoo
オブジェクトが必要な場合、なぜ_return nil
_がFoo.new(0)
にnilを返すと期待しますか?