60分,被NEW关键字捞晕了!!两个new 的例中有什么不一样!
<1>
假如父类中的方法并不是virtual的,子类中的方法也就无法使用override关键字进行覆写,而使用new关键字对父类中的方法进行覆盖,覆盖后,父类的对象引用来引用子类的对象时,进行调用该同名方法,会调用父类的方法,虽然实际上引用的是子类的对象。
using System;
using System.Collections.Generic;
using System.Text;
namespace Hello
{
interface IHello
{
void sayHello();
}
class Hello : IHello
{
public virtual void sayHello()
{
Console.WriteLine( "Hello! ");
}
}
class HelloLee : Hello
{
public override void sayHello()
{
Console.WriteLine( "Hello Lee! ");
}
}
class HelloCoderLee : HelloLee
{
public new void sayHello()
{
Console.WriteLine( "Hello CoderLee! ");
}
}
class Program
{
static void Main(string[] args)
{
IHello sayHello;
sayHello = new HelloCoderLee();
sayHello.sayHello();
Console.ReadLine();
}
}
}
输出为:
Hello Lee!
<2>
而我查看SDK文档:
使用 new 修饰符显式隐藏从基类继承的成员。
若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,
并用 new 修饰符修饰它。
// cs_modifier_new.cs
// The new modifier
using System;
public class MyBaseC
{
public static int x = 55;
public static int y = 22;
}
public class MyDerivedC : MyBaseC
{
new public static int x = 100; // Name hiding
public static void Main()
{
// Display the overlapping value of x:
Console.WriteLine(x);
// Access the hidden value of x:
Console.WriteLine(MyBaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
输出
100
55
22
<3>
看msdn:
new 关键字可以显式隐藏从基类继承的成员。
隐藏继承的成员意味着该成员的派生版本将替换基类版本
现在有一问题:为什么 <1> 中是输出Hello Lee!(父类)
而不是输出Hello CoderLee!(子类)
new关键字不是说隐藏基类吗,
也就说调用子类
这个例子与 <2> 例有什么不同
为什么 <2> 例中调用的是子类的属性
顺便问一下,怎样才能理清new 的使用
[解决办法]
多态的时候 new 方法就不起作用了
如果要被子类override那就要virtual
new 是不行的 实际上调用的还是父类的方法 这个没办法解决
只有在写父类的时候所有的方法都virtual一下
[解决办法]
new一个是在调用的时候使用,这个就很简单了,就是实力化一个对象。
当new 出现在 类里面 public 前面的时候是不是就晕了呢?其实不用去管它。
> > 为什么 <1> 中是输出Hello Lee!(父类)
这个呢是因为编译的时候,调用的方法的内容就固定了,就是调用父类,不会考虑子类。
而另一种方法就是“动态”的,会考虑子类李重写的方法。
就是这个意思。感觉一下:)
------解决方案--------------------
我来解释你的程序为什么输出了Hello Lee!
你在HelloCoderLee类中用public new void sayHello()实际上是添加了一个新方法这个方法跟你所继承的HelloLee类中的sayHello方法毫无关系,什么叫new呢?等于在这个HelloCoderLee类中存在两个sayHello方法,而
IHello sayHello;
sayHello = new HelloCoderLee();
sayHello.sayHello();
这三句中sayHello实际上是实现了接口IHello,也就是说在sayHello.sayHello();时实际上是调用的HelloLee中的方法,上边说过了HelloCoderLee方法实际上有两个sayHello方法,如果你改成这么写
HelloCoderLee sayHello = new HelloCoderLee();
sayHello.sayHello();
就应该是Hello CoderLee!了
[解决办法]
如果,HelloLee还有其它实现,这样HelloCoderLee也能一一继承下来,不仅限于接口
如果这样声明:class HelloCoderLee : HelloLee
HelloCoderLee只能继承HelloLee对于IHello接口的实现,而不能改写
而class HelloCoderLee : HelloLee,IHello 就可自己实现IHello的接口
[解决办法]
其实这个new的语法是C#里面独有的,而且你不写也不会出错,只会有一个警告。
new的意思是,派生类的方法将隐藏基类的方法,这个隐藏并不是说基类的方法无法调用了,这个隐藏是与重写相对的,隐藏了,当使用基类调用的时候,这个方法就能显现出来。。而重写了,无论你用什么类型调用,总是调用重写的方法,因为方法被“重新写过”了。
[解决办法]
为什么要有这个new,主要是因为程序版本的问题,一般而言,应该现有父类才能有派生类,但使用派生类者当然可以定义自己的方法,比如sayHello,但后来父类发现sayHello这个方法蛮好,也取了同名的方法(父类可不知道它的派生类已经用了这个方法名),那么,显然,如果你用父类的引用调用这个sayHello方法的时候最好还是调用父类自己的,而不是派生类的(这才符合你的程序的本意),当然这也是C#默认的处理方式,但这样编译器好歹在编译的时候会给你一个警告.
我们加上new的意思是告诉编译器 "我知道我在干什么,你别来烦我 ",所以编译器就不哼了
同理这个new出来的方法只有子类对象自己能用的到,所以无论你是使用基类的引用还是接口的引用别人都访问不到.