关于“父类引用指向子类对象”

很多人在初次接触设计模式的时候,最大的疑惑莫过于碰到这样的句子:(父类Animal和子类Dog) 

Animal a2  =   new  Dog();


这是什么玩意儿?究竟有什么用途,我直接用子类对象不就完了?


我们就来解释一下: 
--这是什么玩意儿?
re:这种用法叫做“父类引用指向子类对象”(跟绕口令似的),或者叫“父类指针指向子类对象”,指的是定义一个父类的引用,而它实际指向的是子类创建的对象。功能上相当于子类的“向上转型”,或者“上溯对象”,
上面的语句也可以写成:

Animal a2  =   new  Animal();
Dog    dog 
=   new  Dog();
a2 
=  dog;


将子类对象赋给父类的引用就是向上转型,Animal a2 = new Dog();中的new Dog()就是实例化一个没有名字的对象,然后转型给父类的引用a2,仅此而已。

--究竟有什么用途?
re:一般来说,一个对象实例创建完就定死了,比如dog,如果程序里的变量写dog的话,万一以后发生变化就要改代码了。那么事先就不写死dog,而是写父类Animal,那么以后用到Animal的地方,用dog实例,cat实例都可以取代,不用改实例名了。说玄乎一点,也就体现了面向对象“多态”的特性。

下面看一个很简单的例子,就更加明白了:

复制代码
     class  Animal
    {
        
private  String type  =   " Animal " ;
        
public   virtual   void  showLegs()
        {
            Console.WriteLine(
" This is an {0} , Animal always has legs " ,type);
        }
    }
    
class  Dog : Animal
    {
        
private  String type  =   " Dog " ;
        
public   override   void  showLegs()
        {
            Console.WriteLine(
" This is a {0} , Dog has four legs " , type);
        }
    }
    
class  Glede : Animal
    {
        
private  String type  =   " Glede " ;
        
public   override   void  showLegs()
        {
            Console.WriteLine(
" This is a {0} , Glede has two legs " ,type);
        }
    }

    
class  test
    {
        
static   void  Main( string [] args)
        {
            Animal a1 
=   new  Animal();
            Animal a2 
=   new  Dog();
            Animal a3 
=   new  Glede();
            a1.showLegs();
            a2.showLegs();
            a3.showLegs();
            Console.ReadLine();
        }
    }
复制代码

 

 结果:

This  is  an Animal , Animal always has legs
This 
is  a Dog , Dog has four legs
This 
is  a Glede , Glede has two legs

 

真正明白了这些,也就该接触设计模式领域了。

最后唠叨两句:

·因为a2,a3都是子类的对象,所以调用起来,也都是调用的子类的方法(当然前提是它们都override了父类方法,诸位可以试着把两个子类中的override替换成new,结果就完全不一样),有人把这叫做“关注对象原则”。

·向上转型是一定没有错的,就好比你说“狗是动物”是成立的,反之,向下转型就要注意了,你不能说“动物是狗”。

也不知道说明白没有,先下了。。。


---------------------------------------------------------------------------------------------------------------

如何理解“基类的引用即便是指到了派生类对象上,但是它也只能引用派生类中的基类那一部分”?

一.首先要了解new作为修饰符时是干什么的:
不使用override的情况下,如果子类与父类的成员重名,编译器会报警,所以需要一个new作为修饰符,来隐藏基类的同名成员,new的作用就是告诉父类:“嗨,我不想用你留给我的成员,我要隐藏它,并且我自己建一个与之同名的成员”。——没办法,这孩子就是这么倔。
所以,修饰符new并不能体现多态,只是在子类新建了一个成员而已。除了名字比较吊外(敢跟父类成员的名字相同,呵呵),跟子类的其他成员没什么两样。
二.了解父类引用指向子类的局限:
一旦声明了什么类型,则它就只能调用这个类型的方法,所以,父类的引用即便是指到了子类对象上,但是它也只能调用父类的那一部分方法。
比如,把上面代码中的Dog类添加一个父类中没有的成员guard():

class  Dog : Animal
    {
        
private  String type  =   " Dog " ;
        
        
public   override   void  showLegs()
        {
            Console.WriteLine(
" This is a {0} , Dog has four legs " , type);
        }
        
// 新成员
          public   void  guard()
        {
           Console.WriteLine(
" Dog can Guard the house " );
        }
    }
同样使用Animal a2  =   new  Dog();
你会发现:
a2.guard()是不能访问的,因为父类没有guard方法!
a2只会访问Animal类型的成员。
同理,Dog类中如果把override改成了new,则showLegs()方法就只是子类中的一个普通方法,其不能被a2访问到,a2将访问Animal的showLegs()方法。

至于为什么override就能实现访问子类的方法呢,这就是多态的好处嘛!override正是体现了多态。 在每一个类中都有一个多态表,里面保存的是该类中的多态成员的地址,类的多态性也就是用它来实现的,具体的内容你可以看看相关的资料。 
如果有空请参考:
new修饰符:
http://msdn.microsoft.com/zh-cn/library/435f1dw2.aspx
了解何时使用 Override 和 New 关键字:
http://msdn.microsoft.com/zh-cn/library/ms173153.aspx

以上文字均为转载,原文链接:http://www.cnblogs.com/PatrickChen/archive/2009/02/10/1323115.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值