вызвать новый метод подкласса из базового класса - PullRequest
3 голосов
/ 02 марта 2010

У меня есть несколько классов, подобных этому

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public override void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

Работает правильно, печатает "МЕТОД ИЗ С"

НО

если у меня такая ситуация

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

печатает «МЕТОД ОТ А». Как я могу получить такое же поведение первого примера без принятия преобразования или изменения метода с переопределением?

Ответы [ 3 ]

11 голосов
/ 02 марта 2010

Вы не можете - эта разница в поведении - весь смысл использования виртуального / переопределения.

Когда вы объявляете метод с помощью «new», вы говорите: «Я знаю, что скрываю метод с той же сигнатурой, а не переопределяю его; я не хочу полиморфного поведения».

Аналогично, когда вы объявляете метод без указания «virtual», вы говорите: «Я не хочу, чтобы подклассы могли переопределять этот метод».

Почему ты хочешь это сделать? Вы на самом деле просто пытаетесь переопределить метод, который не был объявлен виртуальным? Если так, то нет никакого пути к этому - и на то есть веская причина. Если автор не разработал класс с учетом полиморфизма, он может легко сломаться, если вы сможете переопределить метод.

Конечно, если вы объявите переменную типа подкласса, например:

C c = new C();
c.method();

тогда будет вызывать только что объявленный метод.

2 голосов
/ 02 марта 2010

Как сказал Джон, избегай этого. Но

static void Main(string[] args)
    {
        A a = new C();

        (a as C).method();

        Console.ReadLine();
    }
1 голос
/ 10 декабря 2012

Вы можете использовать динамическое ключевое слово для вызова этого метода.

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}
...