在上一篇Blog中给大家留了一个问题,如果大家有上机去尝试一下,就会知道答案是1了。虽然代码用的是Java,但是这个问题是具有同性的,即使换了C#去写,也会让我们思索一番。下面先从Java的角度去阐述一下这个问题。
        对于这个答案的解释,我们可以从两个方面去看:一是从语义的角度;首先,g这个方法对于类C而言是继承自类B,那么就应该与类B中的方法g的行为完全一致,而方法g调用了方法f,其访问修饰符是private,也就是说不可以被覆盖(override)了,从这里就可以知道方法g的行为(调用类B中的方法f)就已经确定了。所以类C继承了类B,使用方法g就不能乱来了,就得乖乖的按照类B定义好的方法g办事了;
        二是从底层实现的角度;如果大家觉得上面的说法不够说服力的话,还是让我们来点更加细节的吧。我们都知道创建一个实例的时候,会根据继承层次相应地调用不同的构造函数。当类C实例化的时候,先调用类A的构造函数,接着是类B的,最后是类C的,由于我们这里并没有为这三个类定义特殊的构造函数,默认不带参数的构造函数就会被调用了。那么在类C的一个实例被创建的时候,到底发生了什么呢?首先是类A的构造函数被调用,也就是在heap中为这个实例分配了内存以存放实例变量(instance variable)和方法的指针,由于类A中没有实例变量,就只为存放方法g的指针分配了空间,同时这个指针的内容是可以被修改的;接着类B的构造函数被调用,由于方法g被override了,那么原来存放着方法g指针的地址就会被修改,指向类B的方法g,而方法g中调用的方法f由于其访问修饰符是private,所以这个被调用的方法f的指针值就已经固定了;接着类C的构造函数被调用,只是增加了方法f的指针,注意是增加。综上所述,由于在Java中,所有类方法都是虚函数,都是可以被继承的,因此,如果访问修饰符不为private,都会在类构造函数被调用的时候分配空间以初始化这些方法的指针。
        以下是上一篇blog中Java代码所对应的C#代码:

using System;
namespace DefaultNamespace
{
    public class Test {
        public static void Main(string[] args) {
            A ref1 = new C();
            B ref2 = (B)ref1;
            Console.WriteLine(ref1.g());
            Console.WriteLine(ref2.g());
        }
    }
    
    public class A {
        private int f() {
             return 0;
        }
        public virtual int g() {
             return 3;
        }
    }
    
    public class B: A {
        private int f() {
             return 1; 
        }
        public override int g() {
             return f();
        }
    }
    
    public class C: B {
        public int f() {
             return 2;
        }
    }
}

从以上代码,我们可以发现,C#对于继承体系有着更为严格和具体的定义。譬如需要通过virtual关键字来说明该方法是虚函数,是可以被override的以及override的关键字的使用等。
        呼,终于都说完了这一串让自己战战兢兢的文字。还是一句老话,自己明白容易,要讲清楚就难了。关键还是认识不够深刻啊,请各位多多指点了。

转载于:https://www.cnblogs.com/perhaps/archive/2005/01/06/87687.html

一个关于继承和多态的问题(思索篇)相关推荐

  1. 啥是面向对象?啥是封装、继承、多态?看看这篇文章就够了

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 面向对象 首先我们来扯面向对象吧 面向对象呢也有一个高大上的名字叫OOP,是现在最 ...

  2. java写一个外网访问的接口_【JAVA基础】一个案例搞懂类、对象、重载、封装、继承、多态、覆盖、抽象和接口概念及区别(中篇)...

    0 前言 初学JAVA时,总会对一些概念一知半解,相互混淆,不明其设计的用意,如类.对象.重载.封装.继承.多态.覆盖.抽象类.接口概念.为便于理解和巩固,本文将基于一个案例及其变形,展现各个概念的定 ...

  3. 一个经典实例理解继承与多态原理与优点(附源码)---面向对象继承和多态性理解得不够深刻的同学请进...

    一 引子 都说面向对象的4大支柱是抽象,封装,继承与多态.但是一些初涉编程的开发人员,体会不到继承与多态的妙用,本文就试以一个经典实例来诠释继承与多态的用武之地.本实例的需求来自<重构>一 ...

  4. 一个关于封装、继承、多态的问题

    前两天给一刚毕业的小伙子面试,问java基础学的咋样,答还行,so问了一题蛮经典的问题,结果没答好,小伙伴们可以参考参考 类A public class A {     public String s ...

  5. 【Java设计模式 面向对象设计思想】一 再谈面向对象和封装、抽象、继承、多态四大特性

    回看最初的目标:[Java设计模式 学习目标及大纲]高质量代码的标准及实现路径在这篇Blog里我们明确了什么是高质量的代码:易维护.易读.易扩展.灵活.简洁.可复用.可测试,也知道高质量代码的达成路径 ...

  6. Go 学习笔记(36)— 基于Go方法的面向对象(封装、继承、多态)

    Go 面向对象编程的三大特性:封装.继承和多态. 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 继承:使得子类具有父类的属性和方法或者重新定义.追加属性和方法等 多态:不同对象中同种行为的不 ...

  7. Python中的继承和多态

    本文以生活中的基础现象为切入点,主要介绍了Python基础中继承和多态,包括单继承.多继承的语法.多态常见的 "鸭子类型". 以及如何重写父类的方法都做了详细的讲解. 一.继承的介 ...

  8. python 继承和多态

    python 继承和多态 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Ba ...

  9. java 封装 继承 堕胎_JAVA封装、继承、多态

    封装 1.概念: 将类的某些信息隐藏在类的内部,不允许外部程序访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: a.只能通过规定的方法访问数据 b.隐藏类的实例细节,方便修改和实 ...

  10. Python面对对象编程——结合面试谈谈封装、继承、多态,相关习题详解

    1.面向对象的三大特征 封装:属性和方法放到类内部,通过对象访问属性或者方法,隐藏功能的实现细节.当然还可以设置访问权限; 继承:子类需要复用父类里面的属性或者方法,当然子类还可以提供自己的属性和方法 ...

最新文章

  1. 【radar】毫米波雷达相关数据集(检测、跟踪、里程计、SLAM、定位、场景识别)总结(1)
  2. python均线斜率_一根20日均线闯天下?——量化回测“压箱底指标”
  3. 雷蛇灯光配置文件_雷蛇猎魂光蛛竞技版机械键盘评测
  4. .net 深入系统编程(三)
  5. Intellij Idea 离线安装插件
  6. python线程数组_Python多线程
  7. cad图框尺寸标准图_基于AutoCAD2020的动态图框制作与图纸比例问题
  8. 使用authentication进行身份验证,与Forms表单登陆
  9. ibm服务器硬件故障检测工具,IBM服务器故障提示Memory/bttery problems were detected
  10. FastReport 安装方法
  11. How to Write a simple UEFI EDKII Application:如何编写一个UEFI简单的应用程序[5]
  12. excel数据处理,表格数据处理成树形结构
  13. 共议新时代的文化自信与守正创新,第十四届文化中国讲坛举办
  14. 旧电脑很卡怎么重新安装电脑系统?
  15. java实现报数游戏
  16. 苹果cms首页文件html,苹果cms首页视频不更新怎么解决
  17. 使用谷歌学术检索论文小技巧
  18. html 利用 frameset 进行简单的框架布局
  19. vim 错误提示解决:The ycmd server SHUT DOWN (restart with ‘:YcmRestartServer‘). Unexpected exit code 1.
  20. java 实现图片的合成

热门文章

  1. error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用
  2. Hexo报错Usage: hexo command处理及图片显示问题
  3. Volley源码解析(二)
  4. Flink 1.10 SQL、HiveCatalog 与事件时间整合示例
  5. MediaCodec进行编解码AAC(文件格式转换)
  6. python基础篇–变量和简单的数据类型(下)
  7. 画数轴的步骤_上分助手北师大数学七年级上册第二章有理数第二节数轴详细拆解...
  8. mysql数据库+查询+sequence_MySQL数据库InnoDB存储引擎Log漫游
  9. 杭电acm1000c语言答案,c语言,杭电acm1328这题怎么做啊,求提示!!!
  10. html中src中的url,HTML 中的 href\src\url