2016-06-16 3 views
0

私は比較的新しいルビーです。オブジェクトを初期化すると自動的にその親クラスが初期化される可能性はありますか?スーパークラスのメソッドを初期化するためにスーパークラスを手動で呼び出すことはできますが、スーパークラスを明示的に呼び出さなければ自動的にこれが行われるのでしょうか?Keepinig Ruby OOP DRY

Javaでは発生します。 Javaオブジェクトを初期化すると、その親クラスのオブジェクトは自動的に初期化され、その親クラスのコンストラクタが自動的に呼び出されます。

これがルビでは発生しない場合、新しい親クラスオブジェクトが子クラスとともに自動的に作成(初期化)されないことを意味しますか?

これが当てはまる場合、私の問題を解決する最も良いOOPの方法は何ですか?

クラスBは、Aの子です。AにはXresultという属性があります。 Bの初期化はオブジェクトXに渡され、Bの初期化に渡されたオブジェクトXを使用してXresultをAに設定する必要があります。

1つの方法は、XからXresultを取得して属性を設定できるところで、XをAの初期化に渡すことです。しかし、これを行うには、Bの初期化でスーパー(X)を行う必要があります。これは乾燥しません。私にはBのような子供がたくさんいます。

+0

Xresultをメソッドにすることはできますか?スーパーの属性にアクセスするのではなく、メソッドを呼び出すことができます。 –

+0

しかし、私はすべてのBでこのメソッドを反復的に呼び出す必要があります。 – Rpant

+0

"新しい親クラスオブジェクトが自動的に作成されないということですか?" "親オブジェクト"はありません。それはすべて同じオブジェクトです。 –

答えて

1

ただし、これは明示的にsuperを呼び出さないと自動的に発生します。

いいえ、サブクラスに独自のinitializeメソッドがある場合、自動的には発生しません。ただし、サブクラスが独自のinitializeメソッドを定義していない場合は、そのサブクラスを親クラスから継承します。

1つの方法は、XからXresultを取得して属性を設定できるところで、XをAの初期化に渡すことです。しかし、それを行うには私はBの初期化でスーパー(X)を行う必要があります。 (私は多くのB子どもがいます)

私はこれは完全に容認できる解決策だと思います。 super xのような1行のコードを複製することは避けられません。


言われて、あなただけのAのinitializeメソッドは、あなたがそうのようにBで定義するメソッドを呼び出す有することができること:

class A 
    def initialize(x) 
    @x = x 
    initialize_subclass if respond_to?(:initialize_subclass) 
    end 
end 

class B < A 
    def initialize_subclass 
    puts 'doing B-specific stuff' 
    end 
end 

B.new(5) 
A.new(6) 
+0

誰も応答しない場合はこれを回答として受け付けます。 – Rpant

+1

'' 'initialize_subclass'''で提案されている解決策は悪いデザインだと思います。 Rubyはすでにこの動作のための構成を持っています( '' 'initialize''と' '' super''')。これは、現在の実装者がイニシャライザを実装してはならないことを知っておく必要があるので、トラブルを求めています。 。また、潜在的なサブクラスがメソッドを追加したかどうかを確認し、それを魔法のように呼び出すことは私にとっても間違っているようです。 –

+0

しかし私はすべての実装者とスーパークラスを自分で作成しています。そして答えは私に何か新しいことを学ぶのに役立ちます。それを受け入れる。 – Rpant

2

のJava

でも、Javaで、あなたがする必要があります「no-argsコンストラクタ」がなくなるとすぐに手動でスーパーコンストラクタを呼び出します。

ルビーあなたはサブクラスinitializeで手動superを呼び出す必要がRubyで

。それはスーパークラスの初期化子ではできない追加の作業が必要な場合にのみ、イニシャライザをオーバーライドするだけで完全にOKです。 Javaでsuperへの呼び出しがinitializer

class Child < Parent 
    def initialize(a, b, c) 
    @b = b 
    @something = @a + @c 
    super(a) 
    end 
end 

の最初の行にする必要はありませんとは違って、私はRpantでコメントを明確にするために、質問を編集:「ルビーのように見える、方法は単純です基底クラスから派生クラスにコピーされました "

いいえ、メソッドはコピーされません親クラスから子クラスに。 initializeメソッドは、Rubyの通常のメソッドです。Javaのような特別な動作はありません。あなたがそれを提供すれば、それは呼び出されます。オブジェクトまたは割り当てメモリを初期化する必要はありません。これは.newhttp://ruby-doc.org/core-2.2.0/Class.html#method-i-new)で行われます。あなたのスーパークラスの

理由initializeは、メソッド・ルックアップ・パスに嘘を呼ばれていません。

メソッドがオブジェクトで呼び出された場合、その後、クラス階層が検索されます。メソッドが見つかるとすぐに、検索が停止し、メソッドが呼び出されます。そこから、必要に応じてsuperに電話するのはあなたの責任です。

+0

しかし、Javaは常にスーパークラスを初期化しようとします。あなたが言った場合、スーパークラスにゼロ引数のコンストラクタがないと、ランタイム例外がスローされます。あなたの答えは依然として参考になりました。ルビーのように見えますが、メソッドは基本クラスから派生クラスに単純にコピーされます。 – Rpant

+0

私はあなたのコメントに答えて答えを更新しました。 –

1

他の回答を補完する:ルビーのinitializeではないコンストラクタです。それは、あなたがクラスで持っている可能性のある他のすべてのメソッドと同じ、普通のメソッドです。唯一の違いは、newオブジェクト(オブジェクト作成プロシージャの一部として)のときにinitializeが呼び出されていることです。あなたはBでこのメソッドを持っていた場合

class B < A 
    def hello 
    puts 'whatever' 
    end 
end 

あなたはそれが自動的に親のhello、あなたの希望を呼び出すことを期待しないでしょうか?だからあなたの答えがあります。