Java からのオーバーライド アノテーションを Ruby で複製することは可能ですか?
概要
Java では、Override アノテーションがスーパークラスに次のメソッドがあるかどうかをチェックすることはわかっています。
class Animal {
public void speak () {
System.out.println("Hello!");
}
}
class Dog extends Animal {
@override
public void eat () { //this kind of stuff
System.out.println("omnomnom");
}
}
Rubyでこれを(関数か何かとして)行う方法はありますか?
解決策
最上位の eigenclass でクラス メソッドを定義すれば、これは比較的簡単です。
class Animal
def speak; :ok; end
def self.override *ms
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) missing " \
"in #{self}’s ancestors" unless ms.empty?
end
end
class Dog < Animal
override :speak
def speak; :ok; end
override :eat
def eat; :ok; end
end
上記は印刷されます
# ⚠️ [:eat] method(s) missing in Dog’s ancestors
ここでオーバーライドする呼び出しは、引数を指定した Module#module_function の呼び出しに似ており、コード内の任意の場所に配置して、必要な数のメソッド名を受け入れることができます。
eigenclass インスタンス変数を使用して、Java バージョンに近づけることもできます。
class Animal
def speak
:ok
end
def self.inherited(base)
base.instance_variable_set(:@override, ->(*ms) {
ms = ms - Animal.instance_methods
puts "⚠️ #{ms.inspect} method(s) without super" \
unless ms.empty?
})
end
end
class Dog < Animal
@override[:speak]
def speak; :ok; end
@override[:eat]
def eat; :ok; end
end
TracePoint や Module#method_added を使用して Java 構文を完全に複製することもできますが、私はそれがあまり明示的ではないため、上記のように直接メソッド名を渡すことを避けます。