c#为什么要用new 修饰子类方法
在C#中,在子类中用new修饰一个方法的目的就是在子类中用该方法隐藏父类中对应方法,这样,对于同一个方法而言,用父类的实例对像来调用和用子类的实例对象来调用就各不相同,实现了在子类中用子类方法隐藏父类的方法。
现在考虑一种情况,在程序中用子类实例化了一个对象,而现在需要调用该对象对应的父类中的已被子类隐藏了的方法,该如何操作?看以下代码:
class A
{
public int age;
public void f()
{
age++;
...
}
}
class B:A
{
...
public new void f( )
{
}
...
}
...
static void Main()
{
class B b=new B();
...
b.f().
}
在Main中,f方法是对应对class B的方法,而不是class A的f方法。现在有一个需求,执行完了b.f()后,要执行Class A中的f方法。怎么办?按照我以前的做法,再实例化一个A类对象c,再将b对象中的成员的当前值赋给c,再执行c.f()。这就是我的做法,当类很简单时,这种方法也不失为一种方法,但当类很复杂时,要完成前述成员赋值工作是件很恐怖的事,甚至是完不成的事。另外,这样做又生成一个几乎与b对象完全一产的对象,这就对资源的利用效率来说是非常不利的。
那有没有更好的方法呢?其实,有一种很妙的方法可完美解决问题,先上代码:
...
A c=(A)b;
c.f();
不要轻视,一定要仔细看好上面这两句其貌不扬,古里古怪的语句,里边的道理妙着呢,首先看第一句,
A c=(A)b;
首先要说明的此语句没有产生新的A类实例对象,因为这是浅复制,那c是什么,c就是一个指向b对象所指向的B类实例对象且标识为类A的对象,这话咋就这么绕呢?换句话说,c是一个引用型变量,类型为class A,变量名为c,引用的标的的是b所引用的标的,这种变量我们称为父类声明子类对象引用的变量。
即然c是class A类型的,那么c.f()当然是执行了父类A中的方法了,而且由b所引用的实例对象在执行,现在所有的问题是不是都解决了?
如果你还看不出文中的微妙之中,那实在可能是我没有说清楚,或许这个道理真的很微妙,不细心还真看不出来。为了便于理解,请看以下代码:
class Animal
{
public int age;
public void call()
{
Console.WriteLine("I am an animal.I am {0}", age);
}
}
class Cat : Animal
{
public new void call()
{
Console.WriteLine("I am a cat.I am {0}", age);
}
}
public class Program
{
public static void Main()
{
Cat cat = new Cat();
cat.age = 3;
cat.call();
Animal cat2 = (Animal)cat;
cat2.call();
}
}
运行的结果是:
cat2调用call方法显示其年龄也是3岁,可知cat2指向的正是cat指向的。
总结一下,以上代码中b和c指向同一个B类对象,但b可执行B类中的所有方法,c可执行A类中被隐藏了方法,对一个子类实例对象,可再定义一个父类声明子类对象引用的变量,就轻松调用子类对象的new方法和被new方法隐藏的父类方法了。
为了巩固一下理解,将以述稍加变化一下,仍是父类声明子类对象引用的变量的例子。如下:
public static void Main()
{
Animal cat = new Cat();
cat.age = 3;
cat.call();
Cat cat2 =(Cat)cat;
cat2.call();
}
运行结果为:
注意:C#可以定义父类声明子类对象引用的变量,但不可以反过来定义子类声明父类对象引用的变量。比如以下代码是无法通过编译的。
A a=new A();
B c=(B)a
这也很好理解,实例对象是按照父类生成的,其中是肯定没有子类的东西的。
再总结,只有父类声明子类对象引用的变量的概念和子类方法new 声明配合起来,才能实现在子类对象中即可使用新方法代隐藏(代替)父类中的方法,也可方便地使用被隐藏的方法。这也许就是C#中为什么要用new 修饰子类方法的主要原因。new的这个作用是override无法提供的。
版权声明:本文为博主原创文章,未经博主允许不得转载。