Стирание метода: почему сказано, что метод производного класса скрывает базовый класс, но работает наоборот? - PullRequest
0 голосов
/ 08 октября 2018
class Animal
{
    public void Foo() { Console.WriteLine("Animal::Foo()"); }
}

class Cat : Animal
{
    public void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Animal::Foo()"
    }
}

Предупреждение компилятора гласит:

Cat.Foo скрывает унаследованный член

Однако на самом деле выходные данные получены из базового класса.Поэтому мне кажется, что наоборот, тот, кого я назвал, скрыт тем, кто находится в базовом классе.

Ответы [ 4 ]

0 голосов
/ 08 октября 2018

Это polymorphism, что означает возможность переопределения методов для производных классов.Вы должны пометить Foo() как виртуальный в базовом классе и override в подклассе следующим образом:

class Animal
{
    public virtual void Foo() { Console.WriteLine("Animal::Foo()"); }
}

class Cat : Animal
{
    public override void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Cat::Foo()"
    }
}

В этом случае Foo() имеет полиморфное поведение!

0 голосов
/ 08 октября 2018

Выходные данные вашей программы - реализация класса Animal Foo, поскольку тип ссылки равен Animal, а не Cat.

Если ссылка имеет тип Catрезультат будет "Cat::Foo()".

Метод Foo класса Cat скрывает метод Foo класса Animal, поскольку базовые классы не могут и не должны знать оих производные классы, в то время как производные классы являются и должны знать свои базовые классы.

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

0 голосов
/ 08 октября 2018

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

Cat c = new Cat();
Animal a = c; // note: a and c refer to the same object

a.Foo(); // output --> "Animal::Foo()"
c.Foo(); // output --> "Cat::Foo()"

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

0 голосов
/ 08 октября 2018

Если вы хотите таким образом, тогда метод должен быть Overrided в производном классе.Отметьте Виртуальный , а также Переопределите

Этот может помочь вам.

class Animal
{
    public virtual void Foo() { Console.WriteLine("Animal::Foo()"); }
}

class Cat : Animal
{
    public override void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Cat::Foo()"
    }
}
...