C # вызывает переопределенные методы подкласса, не зная, что это экземпляр подкласса - PullRequest
4 голосов
/ 24 декабря 2008

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

Когда я сталкиваюсь с одним из этих подклассов, я хотел бы вызвать переопределенный метод, но без знания подкласса. Я могу придумать некрасивые способы сделать это (проверить значение и привести его), но, похоже, должен быть языковой способ сделать это. Я хочу, чтобы список содержал несколько подклассов в одном и том же списке, в противном случае, очевидно, я мог бы просто создать список.

РЕДАКТИРОВАТЬ: Исправлена ​​ошибка в коде, которая приводила к получению очень правильного первого ответа, который я получил :)

Например:

Class Foo 
{
    public virtual printMe()
    {
        Console.Writeline("FOO");
    }
}

Class Bar : Foo 
{
    public override printMe()
    {
        Console.Writeline("BAR");
    }
}

List<Foo> list = new List<Foo>();
// then populate this list with various 'Bar' and other overriden Foos

foreach (Foo foo in list) 
{
    foo.printMe(); // prints FOO.. Would like it to print BAR
} 

Ответы [ 5 ]

8 голосов
/ 24 декабря 2008
class Foo 
{
    public virtual void virtualPrintMe()
    {
        nonVirtualPrintMe();
    }

    public void nonVirtualPrintMe()
    {
        Console.Writeline("FOO");
    }
}

class Bar : Foo 
{
    public override void virtualPrintMe()
    {
        Console.Writeline("BAR");
    }
}

List<Foo> list = new List<Foo>();
// then populate this list with various 'Bar' and other overriden Foos

foreach (Foo foo in list) 
{
    foo.virtualPrintMe(); // prints BAR or FOO
    foo.nonVirtualPrintMe(); // always prints FOO
}
1 голос
/ 24 декабря 2008

Зачем печатать "Foo"? Это не цель виртуальных методов. Все дело в том, что производные классы могут изменить способ работы функции без изменения интерфейса. Объект Foo напечатает «Foo», а объект Bar напечатает «Bar». Все остальное было бы неправильно.

0 голосов
/ 24 декабря 2008

Разве нет решения, в котором вы просто разыгрываете объект, который хотите вызвать, другим:

 foo.printMe(); // prints FOO.. Would like it to print BAR

становится

(Foo)foo.printMe(); // foo can be any derived class of Foo.

Или я пропускаю какую-то часть вопроса?

0 голосов
/ 24 декабря 2008

Чтобы получить поведение, которое вы хотите в этой ситуации, вы можете удалить виртуальный в базовом классе и использовать новый в подклассе.

Однако, как указал Эд Свангрен, с чего бы вы?

0 голосов
/ 24 декабря 2008

Используйте модификатор new , чтобы явно скрыть член, унаследованный от базового класса. Чтобы скрыть унаследованный член, объявите его в производном классе с тем же именем и измените его с помощью нового модификатора. В результате вы получите именно то поведение, которое вам нужно.

Для получения дополнительной информации перейдите сюда: http://geekswithblogs.net/Mohamed/articles/28613.aspx

...