方法擦除:为什么说派生的class方法隐藏了基础class方法,但反过来呢?
Method erasure: why is it said that the the derived class method hides the base class, but it works the other way around?
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 hides the inherited member
然而输出实际上是来自基础 class。所以对我来说似乎是相反的,我调用的那个被基地 class.
中的那个隐藏了
如果您希望以这种方式使用,那么派生的 class 中的方法应该是 Overrided
。检查 Virtual and also Override
This 可能对你有帮助。
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
的 Animal
class 实现,因为引用的类型是 Animal
而不是 Cat
。
如果引用的类型为 Cat
,输出将为 "Cat::Foo()"
。
Cat
class的Foo
方法隐藏了Animal
class的Foo
方法,因为baseclasses 不能也不应该知道它们派生的 classes,而派生的 classes 是而且必须知道它们的基础 classes.
要故意隐藏基数 class 的成员,请使用 new
修饰符。这将告诉编译器隐藏是故意的,并且会抑制警告。
这是因为引用 a
是 Animal 类型。当您使用 Animal 类型的引用时,编译器会假定您想要获得 Animal 行为。覆盖虚方法很好,但是如果你真的隐藏了一个方法,那么你必须显式地使用隐藏class类型的引用来达到隐藏方法。
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()"
从例子中可以看出,当涉及到隐藏时,结果取决于引用类型,而不是对象类型。
这是 polymorphism
,这意味着能够为派生的 classes 重新定义方法。你必须在 base class 中将 Foo()
标记为虚拟,在 sub class 中将其标记为 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()
具有多态行为!
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 hides the inherited member
然而输出实际上是来自基础 class。所以对我来说似乎是相反的,我调用的那个被基地 class.
中的那个隐藏了如果您希望以这种方式使用,那么派生的 class 中的方法应该是 Overrided
。检查 Virtual and also Override
This 可能对你有帮助。
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
的 Animal
class 实现,因为引用的类型是 Animal
而不是 Cat
。
如果引用的类型为 Cat
,输出将为 "Cat::Foo()"
。
Cat
class的Foo
方法隐藏了Animal
class的Foo
方法,因为baseclasses 不能也不应该知道它们派生的 classes,而派生的 classes 是而且必须知道它们的基础 classes.
要故意隐藏基数 class 的成员,请使用 new
修饰符。这将告诉编译器隐藏是故意的,并且会抑制警告。
这是因为引用 a
是 Animal 类型。当您使用 Animal 类型的引用时,编译器会假定您想要获得 Animal 行为。覆盖虚方法很好,但是如果你真的隐藏了一个方法,那么你必须显式地使用隐藏class类型的引用来达到隐藏方法。
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()"
从例子中可以看出,当涉及到隐藏时,结果取决于引用类型,而不是对象类型。
这是 polymorphism
,这意味着能够为派生的 classes 重新定义方法。你必须在 base class 中将 Foo()
标记为虚拟,在 sub class 中将其标记为 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()
具有多态行为!