2011-02-04 15 views

答えて

25

Rubyにはネストされたクラスがありません。

動作を継承する唯一の方法は、まあ、継承によるものです。

コードを機能させるには、ネストされたクラスをサポートする言語を使用する必要があります。

  • BETA、入れ子になったクラス(およびその後継gbeta)を導入し、言語
  • Newspeak
  • :これは 信じられないほどきちんとして強力な機能ですが、私は残念ながらクラスを入れ子にしている2つだけの言語を知っています

私は他の何かを知りません。

Javaにはネストされたクラスと呼ばれる構造がありますが、デザインにはいくつか不都合な制限があります。

は、上記のあなたの例では、それはA内にネストされクラスBではありません、それはA内にネストされているB一定です。このことについて考える:A::BC

C = A::B 

さて、クラスが名で入手可能です。 Cがグローバルであり、Aの内部にネストされていないことがすぐに分かるはずです。 (実際には、CObjectの中に入れ子になっていますが、実際にはグローバル定数もないので、それはポイントの横にあります)。CA::Bは同じクラスなので、入れ子にすることも入れ子にすることもできません。唯一の論理的な結論は、クラス自体がネストされていないことです。

ネストされたクラスの定義上の特徴は、メソッドルックアップが継承チェーンの上とネストの外側の2つの次元に沿って進むことです。 Rubyは、すべてのOO言語の99.9%と同様、前者をサポートしています。 (ある意味では、ネストされたクラスはスーパークラスの機能だけでなく、その周囲のクラスの機能も継承します。)

+0

清算コメント+1を私に教えていただきありがとうございます。 –

+2

@Michael Kohl:これらはネストされたクラスではなく、名前空間の定数です。最初の文はそれを正しく得ます。私が思うには、2番目の文章はもともと「クラスを参照している入れ子定数」のようなものを読み、少し強制的に聞こえると思ったので、間違ったことを気にせずに「入れ子クラス」に短縮しました。 Rubyにはクラスメソッドはありませんが、クラスオブジェクトのシングルトンクラスのインスタンスメソッドが正しく組み合わされているため、「クラスメソッド」と呼ばれています。残念ながら、この –

+0

...ショートカット専門用語のようなものは、外部者や初心者のための重大な混乱につながる可能性があります。 StackOverflowのすべての質問を見て、 "普通のメソッドでX(嘲笑、オーバーライド、上書き、エイリアシング、ラッピング、スタブ)をする方法を知っていますが、クラスメソッドでどうやったらいいですか?私たちが使っているショートカットの専門用語のために、彼らはクラスメソッド*のようなものがないので、彼らは実際に自分の質問に対する答えを実際に知っていることを知らない。 –

0

aは、クラスAのクラスメソッドとしましたか?

class A 
    def self.a 
    raise "hi" 
    end 
    class B 
    def b 
     A::a 
    end 
    end 
end 

A::B.new.b 

あなたはインスタンスメソッドとしてそれを維持したい場合は、明らかに例A.new.aのためのように、インスタンス上でそれを呼び出す必要があります。

+0

いいえ、私は本当に内部クラス、Newspeakスタイルを意味しました。 – nes1983

10

これは単なるlulzのためです:

class A 
    def a 
    puts "hello from a" 
    end 

    class B 
    def b 
     Module.nesting[1].new.a() 
    end 
    end 
end 
+0

これは、全体がモジュール内にある場合にのみ機能します。 –

3

あなたは、ネストされたクラスは、その後そう、外側のクラスを拡張したい場合:

class Outer 

    class Inner < Outer 
    def use_outer_method 
     outer_method("hi mom!") 
    end 
    end 

    def outer_method(foo) 
    puts foo 
    end 

end 

foo = Outer::Inner.new 
foo.use_outer_method  #<= "hi mom" 
foo.outer_method("hi dad!") #<= "hi dad" 
4

は、私は通常、このような何かを:

class A 
    def a 
    puts "hi" 
    end 

    def createB 
    B.new self 
    end 

    class B 
    def initialize(parent) 
     @parent=parent 
    end 

    def b 
     @parent.a 
    end 
    end 
end 

A.new.createB.b 
1

あなたの状況によっては、実際には解決策がありますが、かなり簡単です。 Rubyでは、オブジェクトが捕捉していないメソッド呼び出しを捕まえることができます。あなたが得る

A::B.new().b 

:あなたがこれを行う場合

def class A 
    def a 
    raise "hi" #can't be reached 
    end 

    class B 
    def initialize() 
     @parent = A.new 
    end 

    def b 
     a() #does find method a. 
    end 

    def method_missing(*args) 
     if @parent.respond_to?(method) 
     @parent.send(*args) 
     else 
     super 
     end 
    end 
    end 
end 

をそれでは:だからあなたの例のためにあなたができる

!! #<RuntimeError: hi> 

をそれはおそらくのようなものを作るための簡単な方法でありますSubControllerは特定のアクティビティのみを処理しますが、基本的なコントローラメソッドを簡単に呼び出すことができます(親コントローラをイニシャライザの引数として送信することもできます)。

明らかに、これは控えめに使用する必要があります。実際に使用すると混乱する可能性がありますが、コードを単純化するのは本当に素晴らしいことです。

関連する問題