Предотвращение переопределения метода в C # - PullRequest
17 голосов
/ 29 марта 2012

Как я могу предотвратить переопределение метода в производном классе?

В 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, но как я могу запретить классу B переопределять methodB() в первую очередь?

Обновление: Iпропустил ключевое слово virtual в объявлении methodB() класса А, когда я опубликовал этот вопрос.Исправил это.

Ответы [ 4 ]

26 голосов
/ 29 марта 2012

Вам не нужно ничего делать.Модификатор virtual указывает, что метод может быть переопределен.Пропуск это означает, что метод 'final'.

В частности, метод должен быть virtual, abstract или override, чтобы он был переопределен.

Использование *Ключевое слово 1009 * позволит скрыть метод базового класса, но оно по-прежнему не будет переопределять его, т.е. при вызове A.methodB() вы получите версию базового класса, но если вы вызовете B.methodB(), вы получите новую версию.

19 голосов
/ 29 марта 2012

Как вы упомянули, вы можете предотвратить дальнейшее переопределение метода B в классе B, используя sealed с override

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

Использование модификатора sealed вместе с override предотвращает дальнейшее переопределение метода производным классом.

Если вы не хотите, чтобы methodB в классе A было переопределено какими-либо дочерними классами, не отмечайте этот метод virtual.Просто удали это.ключевое слово virtual позволяет переопределять метод в дочерних классах

public void methodA()
{       
}

Используйте ключевое слово sealed в своих классах, чтобы предотвратить дальнейшее переопределение класса

5 голосов
/ 29 марта 2012

В C # функция, не помеченная virtual (которая также включает переопределения виртуальных функций), эффективно закрыта и не может быть переопределена.Итак, ваш пример кода на самом деле не будет скомпилирован, потому что ключевое слово override недопустимо, если в базовом классе нет метода, помеченного как виртуальный с той же сигнатурой.

Если A.methodB () помечены как виртуальные, тоВы могли бы переопределить метод из A, но предотвратить его дальнейшее переопределение в классах, производных более косвенно, используя ключевое слово sealed точно так же, как вы показали.

Следует помнить, что переопределение метода можетбыть предотвращенным, метод скрывается не может.Учитывая ваше текущее определение класса A, следующее определение класса B является допустимым, и вы ничего не можете с этим поделать:

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

Ключевое слово new в основном "нарушает" иерархию наследования / переопределения, поскольку оноотносится к этому одному методу;любая ссылка на класс B, рассматриваемая как класс B (или любой другой производный тип), будет использовать реализацию из класса B и игнорировать реализацию из класса A, если реализация B специально не вызывает к ней обратный вызов.Однако если вы рассматриваете экземпляр класса B как класс A (путем его приведения или передачи в качестве параметра), тогда «новая» реализация игнорируется.

Это отличается от переопределения, гдекласс B, который обрабатывается как класс A и действительно переопределяет виртуальный метод B, все равно будет использовать переопределение класса B метода.Также поймите, что скрытие метода подразумевается (хотя вы получите предупреждение компилятора);если вы объявляете метод с той же сигнатурой в производном классе и не указываете новый или переопределенный, метод базового класса будет скрыт.

1 голос
/ 29 марта 2012

В базовом классе ключевое слово sealed используется только для предотвращения наследования класса, но в унаследованных классах оно может использоваться для предотвращения переопределения метода другим унаследованным классом.

Чтобы предотвратить базовый классМетод класса от переопределения, только не указывайте его как виртуальный.В приведенном вами примере класс B не может переопределить methodB, поскольку 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
    } 
}

РЕДАКТИРОВАНИЕ: уточнил и исправил мое первоначальное утверждение о запечатанном ключевом слове

...