为什么对这个感觉趣呢.因为以前写过两篇关于这个多态和重载混合起来很乱的调用情况分析,自从哪以后,我自认为随便乱写一些继承多态的代码都应该难不到我.但是今天看到一段代码有一个地方计算错误了,所以有必要写下来巩固一下,但是我之前总结的是没有问题的,今天就用以前总结的方法来看下面代码

代码来自 http://www.cnblogs.com/wangfupeng1988/p/3629312.html 博客

    /// <summary>
/// Father类
/// </summary>
public class Father
{
public void DoWork()
{
Console.WriteLine("Father.DoWork()");
} //虚方法
public virtual void DoVirtualWork()
{
Console.WriteLine("Father.DoVirtualWork()");
} //虚方法
public virtual void DoVirtualAll()
{
Console.WriteLine("Father.DoVirtualAll()");
}
} /// <summary>
/// Son类
/// </summary>
public class Son : Father
{
//new
public new void DoWork()
{
Console.WriteLine("Son.DoWork()");
}
//new virtual
public new virtual void DoVirtualWork()
{
base.DoVirtualWork();
Console.WriteLine("Son.DoVirtualWork()");
}
//override
public override void DoVirtualAll()
{
Console.WriteLine("Son.DoVirtualAll()");
}
} /// <summary>
/// Grandson类
/// </summary>
public class Grandson : Son
{
public override void DoVirtualWork()
{
base.DoVirtualWork();
Console.WriteLine("Grandson.DoVirtualWork()");
} public override void DoVirtualAll()
{
base.DoVirtualAll();
Console.WriteLine("Grandson.DoVirtualAll()");
}
}
}

下面Main里面的代码是这样的

    //
Father son = new Son();
son.DoWork();
son.DoVirtualWork();
son.DoVirtualAll();
//
Father aGrandson = new Grandson();
aGrandson.DoWork();
Console.WriteLine("#");
aGrandson.DoVirtualWork();
Console.WriteLine("#");
aGrandson.DoVirtualAll();

我添加了两个分隔符号,方便阅读
先来看第1段的调用,
1.son.DoWork() 先看这个是否满足多态的条件(有继承,有父类引用,有虚方法重写),由于这个方法没有重写,所以不表现出多态,所以子类的new方法DoWork()是不调用的,这里调用父类的DoWork();所以显示Father.DoWork();
2.son.DoVirtualWork();这里也用同样没有方法的重写,所以不表现多态,直接调用父类方法
3.son.DoVirtualAll(); 这里满足条件了,所以这里表现出多态,应该调用子类的方法
这一段结果与上面的分析一样,看下一段,这里我就出错了.

先看
1.aGrandson.DoWork();这没有重写,不表现多态,所以显示Father的方法
2.aGrandson.DoVirtualWork() 这里有重写,是多态,那么显示子类的方法? 问题就在这里等会来分析
3.aGrandson.DoVirtualAll() 这里有重写,是多态,那么调用子类的方法.

这里我们重点来看一下第2,3两个步聚,首先第2步,是存重写,但是重写的是Son的new virtual void DoVirtualWork()方法,所以这一条继承链断了,所以这一步认为是 有父类引用,有虚方法重写,但是没有继承,所以这里不表现多态,那么直接调用Father的方法
然后看第3步,这里是有重写,有父类引用,有没有继承呢?这里有因为Son里面的没有用new关键字,所以这里也还算比较标准的多态调用,其实这里在运行时才去找到Son的DoVitualAll()方法的,平时最多的情况认为Grandson的父类是Father(是从这里代码来看);

这里问题看完了,那我们看一下这个

            Console.WriteLine("#");
Son ss = new Grandson();
ss.DoVirtualWork();

这里有继承,有父类引用,有重写,那么应该调子类的方法
所以调Grandson.DoVirtualWork();由于这个调了父类的,所以再调Son的方法,Son又调了Father的方法,所以结果是
Father.DoVirtualWork()
Son.DoVirtualWork()
Grandson.DoVirtualWork()
都显示出来,差不多写到这里吧,方法还是好用的,我感觉分清楚了这三个条件,这些还是可以角决的.包括加入一些方法重载,只要分清处多态系和非多态系那就是没有问题的.

总结:
1.多态的三个条件,满足就调多态系方法,不满足就正常的调用(这里就可以说是调自身的方法)
2.分清为什么文中的第2步new断开的是继承,而不是其它条件.
3.父类引用指向子类,不管中间有多少层,我们分析的时候要注意,这两层是最重要的,但是也要注意一下,中间是否有断继承这类的情况

C#多态问题的更多相关文章

  1. Java中的多态

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...

  2. C# 工厂模式+虚方法(接口、抽象方法)实现多态

    面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...

  3. C#非常重要基础之多态

    前几天看了一位同志的博客,写的是关于他自己去支付宝面试的经历.过程大体是这样的:问答的时候,前面部分,作者都应答如流,说起自己经验如何之丰富,最后面试官问了作者一个问题:请简述多态的概念和作用.结果这 ...

  4. C++多态详解

    多态是面向对象的程序设计的关键技术.多态:调用同一个函数名,可以根据需要但实现不同的功能.多态体现在两个方面,我们以前学过的编译时的多态性(函数重载)和现在我们这一章将要学习的运行时的多态性(虚函数) ...

  5. 【那些年关于java多态应用】

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal { public abstract void Say();} 子类: public class ...

  6. JAVA多态

    多态是指当系统A访问系统B的服务时,系统B可以通过多种方式来提供服务,而这一切对系统A是透明的.比如动物园的饲养员能够给各种各样的动物喂食.下图显示了饲养员Feeder,食物Food和动物Animal ...

  7. C#多态“说来也说”——逻辑层BLL中的多态使用

    本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/5861842.html 昨天晚上,有个朋友说学了好久,依然没搞 ...

  8. java多态的理解

    面向对象语言中的类有三个特征,封装.继承.多态.封装与继承很好理解,那什么是多态呢? 1.什么是多态? 多态的定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同 ...

  9. java中如何实现多态

    复习基础知识 多态,就是重载和重写.重载发生在一个类中.重写发生在子类,意思就是子类重写父类相同名称的方法.刚学语言有的东西,不必搞得那么清楚,只有知道怎么用就行了,有的问题你要想真正把它搞得很懂,短 ...

  10. OC多态

    要点: 1.多种形态,引用的多种形态对于一个引用变量,可以指向任何类的对象.对于一个父类的引用(类与类之间有一种继承关系),可以指向子类,也可以指向本类,指向的类型不同.当通过此引用向对象发送消息,调 ...

随机推荐

  1. [SAP ABAP开发技术总结]ABAP程序之间数据共享与传递

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. Domion OA 日记

    我现在使用的是IBM的 Lotus Dimion 8.5 以下内容是个人的浅显了解,在此记录下,已作为后续记录的翻看 第一次接触文档型数据库,确实颠覆了我对数据模型的认知,我之前一直用sql的 文档型 ...

  3. JavaScript基础知识之——Location 对象详解

    属性 描述 location.hash 设置或取得 URL 中的锚 location.host 设置或取得 URL 中主机(包括端口号) location.hostname 设置或取得 URL 中的主 ...

  4. 批量创建客户主数据函数SD_CUSTOMER_MAINTAIN_ALL

    分享一下批创建客户主数据函数:SD_CUSTOMER_MAINTAIN_ALL TABLES:T077D,ZCITY,T005S,BNKA,ADRC,KNA1.  DATA: TMP_KTOKD(4) ...

  5. MonkeyRunner学习(2)常用命令

    目录: 1.截图 2.暂停 (时延秒) 3.屏幕操作 4.打印 5.字符串发送到键盘输入(登录输入) 6.唤醒设备屏幕 7.重起手机 8.按键(系统键) 9.回车键 10.for 循环 11.循环截图 ...

  6. 无限极分类,传递一个父ID,返回所有子集

    方法: static public function getChildren($data,$pid){ $arr=array(); foreach ($data as $v) { if ($v['pi ...

  7. Android 自定义对话框

    Android实现自定义对话框效果: 核心代码: package com.example.diydialog; import android.os.Bundle; import android.app ...

  8. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  9. Android最佳性能实践(三)——高性能编码优化

    在前两篇文章当中,我们主要学习了Android内存方面的相关知识,包括如何合理地使用内存,以及当发生内存泄露时如何定位出问题的原因.那么关于内存的知识就讨论到这里,今天开始我们将学习一些性能编码优化的 ...

  10. 在map中根据value获取key

    原文:http://blog.csdn.net/mexican_jacky/article/details/51789548 //根据map的value获取map的key private static ...