12 .net c# oop polymorphism new-operator
我读到newmodifer隐藏了基类方法.
using System;
class A
{
public void Y()
{
Console.WriteLine("A.Y");
}
}
class B : A
{
public new void Y()
{
// This method HIDES A.Y.
// It is only called through the B type reference.
Console.WriteLine("B.Y");
}
}
class Program
{
static void Main()
{
A ref1 = new A(); // Different new
A ref2 = new B(); // Polymorpishm
B ref3 = new B();
ref1.Y();
ref2.Y(); //Produces A.Y line #xx
ref3.Y();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么ref2.Y();生产A.Y作为产出?
这是简单的多态,基类对象指向派生类,因此它应该调用派生类函数.我实际上是Java兼C#编码器; 这些概念让我大吃一惊.
当我们说new隐藏基类函数时,这意味着无法调用基类函数,就我所知,这就是隐藏的含义.
Ser*_*diy 24
在C#中,默认情况下方法不是虚拟的(与Java不同).因此,ref2.Y()方法调用不是多态的.
要从多态性中受益,您应该将A.Y()方法标记为virtual,并将B.Y()方法标记为override.
什么new修改器仅仅是隐藏了从基类继承的成员.这就是你的Main()方法中真正发生的事情:
A ref1 = new A();
A ref2 = new B();
B ref3 = new B();
ref1.Y(); // A.Y
ref2.Y(); // A.Y - hidden method called, no polymorphism
ref3.Y(); // B.Y - new method called
Run Code Online (Sandbox Code Playgroud)
(只是为了补充其他答案,以及我自己的评论.)
当使用时new,类(或结构或接口)将具有两个相同的成员,一个继承自基类型,另一个由类型本身声明.避免这样!
重要提示:仅仅因为你说new,你不会"删除"旧成员.它仍然存在,可以轻松调用.该new成员不会替换继承的成员.它是一个无关的成员,恰好具有相同的名称.
在一个看起来相同的类型中拥有两个或更多成员是不好的.这会导致混乱.考虑一下代码:
interface IOne
{
void Y();
}
interface ITwo
{
void Y();
}
interface IBoth : IOne, ITwo
{
}
class Test
{
static void M(IBoth obj)
{
obj.Y(); // must not compile!
}
}
Run Code Online (Sandbox Code Playgroud)
该类型IBoth有两个成员(都是继承的)看起来相同.根据具体类的obj不同,这些方法可能有不同的实现.这个电话obj.Y()很模糊.您必须转换obj为其中一个基接口才能解决此问题.
然后考虑这段代码:
interface IBase
{
void Y();
}
interface IDerived : IBase
{
/* new */ void Y();
}
class Test
{
static void M(IDerived obj)
{
obj.Y(); // allowed; IDerived has two Y, but one hides the other
}
}
Run Code Online (Sandbox Code Playgroud)
这一次,有两个Y(),但有一个比另一个"更近".所以越近越好.但是,如果您不使用,编译器会给您一个警告new.如果您使用new,除了使编译时警告消失外,其他任何变化都没有.Y()故意制作两个真是个坏主意.
如果基本类型(此处IBase)由其他供应商/供应商编写,则会发生这种情况.示例:Y()在基础没有该功能的时候,您可能已经在界面中引入了它.但随后的供应商IBase将发布他们的产品的新版本,其中IBase有Y().现在,如果您针对新版本编译代码,Y()仍将调用"您的" ,而不是他们的.但它会给出这个警告.如果你包括,警告就会消失new.但最好是(1)Y()如果确定供应商Y()完成工作,则完全删除您的方法,或者(2)将您的Y()方法重命名为某个未使用的名称.
如果你想要的是多态,当然使用abstract/ virtual(仅限类成员)与override(在继承类中)相结合.override不会引入任何新成员,只是现有(继承)成员的新实现.这可以仅针对非静态成员(通常是方法或属性)来完成.
| 归档时间: |
|
| 查看次数: |
2480 次 |
| 最近记录: |