C#为什么要用new 修饰子类方法

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无法提供的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 22:49:50

C#为什么要用new 修饰子类方法的相关文章

override(重写,覆盖) 1、方法名、参数、返回值相同。 2、子类方法不能缩小父类方法的访问权限。 3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。 4、存在于父类和子类之间。 5、方法被定义为final不能被重写。 overload(重载,过载) 1、参数类型、个数、顺序至少有一个不相同。 2、不能重载只有返回值不同的方法名。 3、存在于父类和子

override(重写,覆盖) 1.方法名.参数.返回值相同. 2.子类方法不能缩小父类方法的访问权限. 3.子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常). 4.存在于父类和子类之间. 5.方法被定义为final不能被重写. overload(重载,过载) 1.参数类型.个数.顺序至少有一个不相同.   2.不能重载只有返回值不同的方法名. 3.存在于父类和子类.同类中. 方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现. 重写(O

php获取分类以下的全部子类方法

获取分类以下的全部子类方法: static function getMenuTree($arrCat, $parent_id = 0, $level = 0,$all=True) { static $arrTree; //使用static取代global if(!$all) $arrTree =''; if( empty($arrCat)) return FALSE; $level++; if($level == 1) $arrTree[] = $parent_id; foreach($arrC

Python子类方法的调用(类方法)

class S(object): def Test(self): print("TEST") @classmethod def Test02(cls): print("class") @staticmethod def Test03(): print("Test03")class Test2(S): @classmethod def Test02(cls): print(cls) print("Test02 Method")a

php获取分类下面的所有子类方法

获取分类下面的所有子类方法: static function getMenuTree($arrCat, $parent_id = 0, $level = 0,$all=True) { static $arrTree; //使用static代替global if(!$all) $arrTree =''; if( empty($arrCat)) return FALSE; $level++; if($level == 1) $arrTree[] = $parent_id; foreach($arrC

Java 多态 父类和子类方法的访问控制权限

Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就是一个对象多态的问题. 既然多态,那么访问控制权限就要让父类也能访问. 也就是说,子类重写方法时不能使该方法拥有比父类更严格的访问控制权限. 否则违背了多态,导致向上类型转换后,使用父类变量无法调用该子类私有方法.

synchronized修饰普通方法和静态方法

首先,要知道,synchronized关键字修饰普通方法时,获得的锁是对象锁,也就是this.而修饰静态方法时,锁是类锁,也就是类名.class. synchronized修饰普通方法 Synchronized修饰普通方法时,锁是对象锁(this). 当该类中有多个普通方法被Synchronized修饰(同步),那么这些方法的锁都是这个类的一个对象this.多个线程访问这些方法时,如果这些线程调用方法时使用的是同一个该类的对象,虽然他们访问不同方法,但是他们使用同一个对象来调用,那么这些方法的锁

Java笔记4-do while循环,break,修饰符,方法的调用

do while循环语法:do{ //循环体}while(条件表达式); 注:它是先执行循环体,后再判断的循环结构. 如:int i = 0;do{ System.out.println("i = "+i); i++;}while(i < 10); ---do while一般用在“交互式”的界面循环中.案例: --------------------------break语句与continue语句break可以用在:1). switch语句中, 表示退出某个case块2). 循环

Python3基础 父,子类普通方法同名 子类方法覆盖父类方法

镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.------------------------------------------ code: class Parent : def hello(self) : print('我是本') class Child(Parent) : #child类继承与 parent类 def hello(self) : #parent类中有hello方法,但是这里也定义了一个hello方

java 类继承,父类子类方法调用的过程d

1.Mytank类继承tank,则Mytank里面的公有部分即public 成员和方法在Mytank中是含有的可以调用和赋值,且在MyTank中不要有新的成员变量与tank中的公有成员名称一样,这样会发生调用紊乱,如: Tank tank = new MyTank(); int c = tank.a; 若 tank类中public a= 3: Mytank子类中新定义public a = 2: 则上述代码中的调用将会使得c = 3: 用了父类中的a.