def class A
def a
raise "hi" #can't be reached
end
class B
def b
a() #doesn't find method a.
end
end
end
b から a を呼び出して例外を発生させたい。どうやって?
Rubyにはネストされたクラスがありません。
振る舞いを継承する唯一の方法は、まあ、継承を介することです。
コードを機能させるには、ネストされたクラスをサポートする言語を使用する必要があります。これは非常に優れた強力な機能ですが、残念ながら、ネストされたクラスを持つ2つの言語しか知りません。
私は他に何も知りません。
Javaにはネストされたクラスと呼ばれる構造がありますが、残念ながら設計上の制限がいくつかあります。
上記の例では、内部にネストされているのはクラスB
ではなく、内部A
にネストされている定数 B
ですA
。これについて考えます:
C = A::B
現在、このクラスはとの2つの名前で利用できます。グローバルであり、内部にネストされていないことはすぐにわかります。(実際には、実際にはグローバル定数も存在しないため、内部にネストされていますが、それは重要ではありません。)しかし、とは同じクラスであるため、ネストすることもネストしないこともできません。唯一の論理的な結論は、クラス自体はネストされていないということです。A::B
C
C
A
C
Object
C
A::B
ネストされたクラスの定義機能は、メソッドルックアップが2つの次元に沿って行われることです。継承チェーンの上位と、ネストを介した外部です。Rubyは、すべてのOO言語の99.9%と同様に、前者のみをサポートします。(ある意味で、ネストされたクラスは、スーパークラスの機能だけでなく、周囲のクラスの機能も継承します。)
これはちょっとしたことです:
class A
def a
puts "hello from a"
end
class B
def b
Module.nesting[1].new.a()
end
end
end
私は通常、次のようなことをします。
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
ネストされたクラスで外部クラスを拡張する場合は、次のようにします。
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"
状況によっては、実際には解決策があり、非常に簡単です。Ruby では、オブジェクトによってキャプチャされないメソッド呼び出しをキャッチできます。したがって、あなたの例では次のことができます:
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
したがって、これを行う場合:
A::B.new().b
あなたが得る:
!! #<RuntimeError: hi>
おそらく、特定のアクティビティのみを処理する SubController のようなものを作成する方が簡単な方法ですが、基本的なコントローラー メソッドを簡単に呼び出すことができます (ただし、親コントローラーをイニシャライザーの引数として送信することをお勧めします)。
明らかに、これは慎重に使用する必要があり、あらゆる場所で使用すると混乱を招く可能性がありますが、コードを単純化することは非常に優れています。
a
class のクラス メソッドになるはずだったの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
。