web-dev-qa-db-ja.com

C#でメソッドがオーバーライドされないようにする

派生クラスでメソッドがオーバーライドされないようにするにはどうすればよいですか?

Javaでは、オーバーライドされないようにするメソッドでfinal修飾子を使用してこれを行うことができます。

C#で同じようにするにはどうすればよいですか?
私はsealedの使用を認識していますが、どうやらoverrideキーワードでのみ使用できますか?

_class A
{
    public void methodA()
    {
        // Code.
    }

    public virtual void methodB()
    {
        // Code.
    }
}

class B : A
{
    sealed override public void methodB()
    {
        // Code.
    } 
}
_

したがって、上記の例では、methodB()がクラスBから派生するクラスによってオーバーライドされるのを防ぐことができますが、クラスBmethodB()そもそも?

更新:この質問を投稿したときに、クラスAのmethodB()宣言でvirtualキーワードを逃しました。修正しました。

21
nighthawk457

何もする必要はありません。 virtual修飾子は、メソッドをオーバーライドできることを指定します。省略すると、メソッドは「最終」になります。

具体的には、メソッドをオーバーライドするには、メソッドがvirtualabstract、またはoverrideである必要があります。

newキーワードを使用すると、基本クラスメソッドを非表示にすることができますが、それでもオーバーライドされません。つまり、A.methodB()を呼び出すと、基本クラスバージョンが取得されますが、B.methodB()新しいバージョンを取得します。

28
Kendall Frey

すでに述べたように、sealedwithoverrideを使用することで、クラスBのMethodBがさらにオーバーライドされるのを防ぐことができます。

class B : A
{
    public sealed override void methodB()
    {
        Console.WriteLine("Class C cannot override this method now");
    }
}

sealed修飾子の使用とともにoverrideは、派生クラスがメソッドをさらにオーバーライドすることを防ぎます。

クラスAのmethodBを子クラスでオーバーライドしたくない場合は、そのメソッドにvirtualをマークしないでください。単にそれを削除します。 virtualキーワードを使用すると、メソッドを子クラスでオーバーライドできます

public void methodA()
{       
}

クラスでsealedキーワードを使用して、クラスがさらにオーバーライドされないようにします

20
Shyju

C#では、virtualとマークされていない関数(仮想関数のオーバーライドも含まれます)は効果的にシールされ、オーバーライドできません。したがって、基本クラスに同じシグネチャでvirtualとマークされたメソッドがない限り、overrideキーワードは無効であるため、サンプルコードは実際にはコンパイルされません。

A.methodB()が仮想としてマークされている場合、Aからメソッドをオーバーライドできますが、表示されているとおりにsealedキーワードを使用して、より間接的に派生するクラスでメソッドがオーバーライドされるのを防ぐことができます。

留意すべきことの1つは、メソッドのオーバーライドは防止できますが、メソッドhidingはできません。クラスAの現在の定義を考えると、クラスBの次の定義は正当であり、それに対して何も実行できません。

class B:A
 {
      public new void methodB()
            {
                    //code
            } 
  }

newキーワードは、この1つのメソッドに関連するため、基本的に継承/オーバーライド階層を「破壊」します。クラスB(またはそれ以上の派生型)として扱われるクラスBへの参照は、クラスBの実装を使用し、Bの実装が明確にコールバックしない限り、クラスAの実装を無視します。ただし、クラスBのインスタンスを(キャストするか、パラメーターとして渡すことにより)クラスAとして扱う場合、「新しい」実装は無視されます。

これは、クラスAとして扱われ、仮想methodBを本当にオーバーライドするクラスBが、クラスBのメソッドのオーバーライドを引き続き使用するオーバーライドとは異なります。また、メソッドの非表示が推測されることも理解してください(ただし、コンパイラの警告が表示されます)。派生クラスで同じシグネチャを持つメソッドを宣言し、newまたはoverrideのいずれも指定しない場合、基本クラスメソッドは非表示になります。

5
KeithS

基本クラスでは、sealedキーワードはクラスの派生を防ぐためにのみ使用されますが、継承されたクラスでは、別の継承されたクラスがメソッドをオーバーライドするのを防ぐために使用できます。

基本クラスメソッドがオーバーライドされないようにするには、それを仮想として指定しないでください。提供した例では、元のクラスでmethodBが仮想としてマークされていないため、クラスBはmethodBをオーバーライドできませんでした。

これはコンパイルされます:

class A
{
    public virtual void methodA()
    {
        //code
    }
    public virtual void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}

これはしません:

class A
{
    public void methodA()
    {
        //code
    }
    public void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}

編集済み:封印されたキーワードに関する私の元のステートメントを明確にし、修正しました

1
psubsee2003