Как переопределить универсальный метод? (C #) - PullRequest
1 голос
/ 30 января 2009

Я создаю класс с именем TetraQueue, который наследует System.Collections.Generic.Queue класс, переопределяющий метод Dequeue, вот код:

public class TetraQueue : Queue<Tetrablock>
{
   public override Tetrablock Dequeue()
   {
       return base.Dequeue();
   }
 }

Но когда я пытаюсь скомпилировать это, я получаю:

Ошибка TetraQueue.Dequeue () ': не найден подходящий метод для переопределения TetraQueue.cs

Заранее спасибо.

Как я узнаю, является ли метод виртуальным (чтобы избежать такой ситуации)?

Ответы [ 7 ]

9 голосов
/ 30 января 2009

Два способа узнать, является ли метод виртуальным:

  • Введите "переопределить" в Visual Studio - он предложит вам все методы, которые вы можете переопределить.
  • Просмотр документации - Dequeue не говорит, что она виртуальная, поэтому вы не можете ее переопределить.

РЕДАКТИРОВАТЬ: Другие предлагали скрыть метод. Я настоятельно рекомендую вам не делать это, если вы действительно, действительно не должны этого делать. Это рецепт для сложных сессий отладки и разочарования, когда наследование кажется иногда работающим, а иногда нет, в зависимости от типа ссылки во время компиляции. Blurgh. Если вы не собираетесь специализировать поведение, используйте композицию вместо наследования.

5 голосов
/ 30 января 2009

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

public class TetraQueque : Queue<Tetrablock>
{
   public new Tetrablock Dequeque()
   {
       return base.Dequeue();
   }
}
3 голосов
/ 30 января 2009

К сожалению, метод Dequeue не является виртуальным, поэтому вы не можете его переопределить.

1 голос
/ 30 января 2009

Как уже упоминалось ранее, вы не можете переопределить метод, потому что он не виртуальный. Однако я настоятельно призываю вас не скрывать этот метод. Учтите следующее:

class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            B b = new B();
            A c = new B();

            // Straight A
            a.MyVirtualMethod();
            a.MyNonVirtualMethod();

            // Straight B
            b.MyVirtualMethod();
            b.MyNonVirtualMethod();

            // Polymorphic
            c.MyVirtualMethod();
            c.MyNonVirtualMethod();

            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void MyVirtualMethod()
        {
            Console.WriteLine("Hello world!");
        }

        public void MyNonVirtualMethod()
        {
            Console.WriteLine("Hello world!");
        }
    }

    public class B : A
    {
        public override void MyVirtualMethod()
        {
            Console.WriteLine("Good bye universe!");
        }

        public new void MyNonVirtualMethod()
        {
            Console.WriteLine("Good bye universe!");
        }
    }

Вывод этого кода не очевиден для тех, кто не понимает реализацию.

Hello world!
Hello world!
Good bye universe!
Good bye universe!
Good bye universe!
Hello world!
1 голос
/ 30 января 2009

Бессмысленно переопределять метод, чтобы вызывать только родительский элемент, поэтому, если код, который вы опубликовали, это все, что вы делаете, не переопределяйте его.

Делая ваше TetraQueue очередью , вы говорите, что его можно использовать всегда, когда может быть очередь . Добавляя к нему новый метод, который скрывает оригинальный метод, если вызывающая сторона знает его TetraQueue, тогда вы возитесь с этим контрактом.

Если бы я хотел того же поведения, что и Очередь, я бы использовал Очередь ; если бы я хотел чего-то другого, я бы использовал композицию, а не наследование.

1 голос
/ 30 января 2009

В очереди нет метода Deque q ue, но есть метод Dequeue. Это будет первая ошибка компиляции, если вы исправите это, вы все равно не сможете скомпилировать, потому что это не виртуальный метод.

Используя новое ключевое слово, вы можете снова ввести этот метод, но не забудьте правильно написать имя функции, иначе будет метод .Dequeue и .Dequeque.

Сам вопрос также содержит эту орфографическую ошибку.

1 голос
/ 30 января 2009

Добавьте новое ключевое слово, чтобы скрыть метод в базовом классе.

Хорошая статья о полиморфизме в .net: http://www.akadia.com/services/dotnet_polymorphism.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...