Java または C# に、継承クラスに基本実装の呼び出しを強制する構造はありますか? super() または base() を呼び出すことができますが、呼び出されていない場合にコンパイル時にエラーをスローすることは可能ですか? それはとても便利でしょう..
- 編集 -
私は主にメソッドのオーバーライドに興味があります。
Java または C# に、継承クラスに基本実装の呼び出しを強制する構造はありますか? super() または base() を呼び出すことができますが、呼び出されていない場合にコンパイル時にエラーをスローすることは可能ですか? それはとても便利でしょう..
- 編集 -
私は主にメソッドのオーバーライドに興味があります。
それを行うことは何もありませんし、すべきではありません。
これを基本クラスに持つようなものであれば、私が思いつく最も近いものは次のとおりです。
public virtual void BeforeFoo(){}
public void Foo()
{
this.BeforeFoo();
//do some stuff
this.AfterFoo();
}
public virtual void AfterFoo(){}
そして、継承クラスが BeforeFoo および/または AfterFoo をオーバーライドできるようにします
Java ではありません。C# では可能かもしれませんが、他の誰かがそれについて話さなければなりません。
私が正しく理解しているなら、あなたはこれが欲しい:
class A {
public void foo() {
// Do superclass stuff
}
}
class B extends A {
public void foo() {
super.foo();
// Do subclass stuff
}
}
スーパークラス foo の使用を強制するために Java でできることは、次のようなものです。
class A {
public final void foo() {
// Do stuff
...
// Then delegate to subclass
fooImpl();
}
protected abstract void fooImpl();
}
class B extends A {
protected void fooImpl() {
// Do subclass stuff
}
}
それは醜いですが、あなたが望むものを達成します。それ以外の場合は、スーパークラス メソッドを呼び出すように注意する必要があります。
おそらく、技術的な解決策を使用するのではなく、設計をいじって問題を解決することができます. 不可能かもしれませんが、検討する価値はあります。
編集:多分私は質問を誤解しました。一般的に、コンストラクターまたはメソッドのみについて話しているのですか? 一般的な方法を想定しました。
あなたはこれを見たいと思うかもしれません(スーパー反パターンを呼んでください)http://en.wikipedia.org/wiki/Call_super
基本クラスの動作がオーバーライドされていないことを強制したいが、それでもそれを拡張できることを正しく理解している場合は、テンプレート メソッドのデザイン パターンを使用し、C# ではメソッド定義に virtual キーワードを含めません。
ここですべての返信を読んだわけではありません。しかし、私は同じ質問を考えていました。私が本当にやりたかったことを確認した後、基本メソッドへの呼び出しを強制したい場合、最初に基本メソッドを仮想 (オーバーライド可能) と宣言すべきではなかったように思えました。
ベースコールを強制しないでください。本体でオーバーライド可能な (例: 抽象) 保護されたメソッドを呼び出しながら、親メソッドに必要な動作をさせます。
いいえ、できません。事前または事後アクションを実行する関数が必要な場合は、次のようにします。
internal class Class1
{
internal virtual void SomeFunc()
{
// no guarantee this code will run
}
internal void MakeSureICanDoSomething()
{
// do pre stuff I have to do
ThisCodeMayNotRun();
// do post stuff I have to do
}
internal virtual void ThisCodeMayNotRun()
{
// this code may or may not run depending on
// the derived class
}
}
実行可能なソリューションが組み込まれているとは思わないでください。ただし、それを実行できる別のコード分析ツールがあると確信しています。
EDITコンストラクトをコンストラクターと読み間違えました。問題の非常に限られたサブセットに適合するため、CW のままにします。
C# では、基本型に少なくとも 1 つのパラメーターを持つ単一のコンストラクターを定義することで、この動作を強制できます。これにより、デフォルトのコンストラクターが削除され、派生型が指定されたベースを明示的に呼び出すように強制されます。そうしないと、コンパイル エラーが発生します。
class Parent {
protected Parent(int id) {
}
}
class Child : Parent {
// Does not compile
public Child() {}
// Also does not compile
public Child(int id) { }
// Compiles
public Child() :base(42) {}
}
Java では、コンパイラはコンストラクタの場合にのみこれを強制できます。
コンストラクターは、継承チェーン全体で呼び出す必要があります。つまり、Dog が Animal を拡張する場合、Dog のコンストラクターは Animal のコンストラクターを呼び出す必要があり、Thing のコンストラクターを呼び出す必要があります。
これは、プログラマーが必要に応じてスーパー実装を明示的に呼び出す必要がある通常のメソッドには当てはまりません。
基本実装コードの実行を強制する唯一の方法は、オーバーライド可能なコードを別のメソッド呼び出しに分割することです。
public class Super
{
public final void doIt()
{
// cannot be overridden
doItSub();
}
protected void doItSub()
{
// override this
}
}
public class Sub extends Super
{
protected void doItSub()
{
// override logic
}
}