`

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

阅读更多

        在上一篇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的关键字的使用等。
        呼,终于都说完了这一串让自己战战兢兢的文字。还是一句老话,自己明白容易,要讲清楚就难了。关键还是认识不够深刻啊,请各位多多指点了。

分享到:
评论

相关推荐

    C#第六章 初始继承和多态.pdf

    C#第六章 初始继承和多态.pdfC#第六章 初始继承和多态.pdfC#第六章 初始继承和多态.pdf C#第六章 初始继承和多态.pdfC#第六章 初始继承和多态.pdf

    Educoder题目:Java面向对象 - 封装、继承和多态的综合练习答案解析.md

    Educoder题目:Java面向对象 - 封装、继承和多态的综合练习答案解析

    java基础继承封装多态

    继承是 Java 中的一种机制,允许一个类继承另一个类的属性和方法。继承的语法是使用 `extends` 关键字,例如 `public class Child extends Parent`。在 Java 中,只支持单一继承,也就是说一个类只能有一个直接父类...

    Educoder题目:Java面向对象 - 封装、继承和多态答案解析.md

    Educoder题目:Java面向对象 - 封装、继承和多态答案解析

    关于继承和多态的简单练习

    例如,假设我们有一个`Animal`类有一个`makeSound`方法,`Dog`和`Cat`类都继承了`Animal`并且重写了`makeSound`,那么在运行时,无论我们调用哪个动物的`makeSound`,都会得到相应动物特有的声音,这就是多态的体现...

    C#继承和多态的应用

    C#继承和多态的应用

    C++继承与多态例子

    继承允许我们创建一个新类(子类),它继承了另一个类(父类)的属性和方法,从而实现了代码的重用和扩展。多态则是指同一种行为在不同对象上表现出不同的形式,增强了程序的灵活性。 首先,让我们详细讨论继承。在...

    java面向对象三要素封装继承和多态源码

    java面向对象三要素封装继承和多态源码java面向对象三要素封装继承和多态源码java面向对象三要素封装继承和多态源码java面向对象三要素封装继承和多态源码java面向对象三要素封装继承和多态源码java面向对象三要素...

    浅谈c++的精髓之继承和多态

    **继承**是面向对象编程中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和行为。这一特性极大地提高了代码的复用性,减少了重复代码的编写,同时增强了程序的结构化和组织性。 例如,考虑一个...

    继承和多态笔记.docx

    - **定义**:继承是面向对象编程的一个基本特征,允许创建一个新的类(子类),该类继承自现有的类(父类)。子类可以复用父类的属性和方法,并添加新的特性。 - **特点**: - **单继承**:Java支持单继承,即每个...

    继承和多态.doc

    **继承**是面向对象编程中的一项核心特性,它允许一个类(派生类或子类)继承另一个类(基类或父类)的属性和方法。通过继承,可以实现代码的重用,提高软件开发效率和代码的可维护性。 **使用原则**: 1. **...

    C++经典实例——体现继承和多态

    在提供的压缩包“总实验”中,可能包含了多个C++源文件,每个文件代表一个特定的继承和多态的例子。通过分析这些实例,你可以看到如何在实践中应用这些概念,如何构建类层次结构,以及如何利用多态性提高代码的可...

    C#实验 事件、继承和多态

    继承是面向对象编程的一个特性,它允许一个类(子类或派生类)从另一个类(基类或父类)继承属性和方法。这有助于代码重用和创建层次结构的类。在管理学生信息的场景中,可以定义一个基类“学生”,包含通用属性如...

    Python之继承和多态共7页.pdf.zip

    继承是面向对象编程的一个关键特征,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法。通过继承,子类可以复用父类的代码,减少了代码重复,提高了代码的可维护性和可扩展性。在Python中,我们...

    Java语言程序设计ppt第十一章(继承和多态)

    继承是一种机制,允许一个类继承另一个类的属性和方法,从而避免代码的冗余和提高代码的重用性。在Java中,使用extends关键字来继承父类。 二、继承的应用 继承的应用有很多,例如,设计一个类来对圆、矩形和...

    javascript中如何实现封装,继承和多态

    javascript中如何实现封装,继承和多态

    java继承和多态ppt

    java 继承和多态PPT教程

    C#关于继承与多态的简单练习源码

    根据文件名推测,这是一个关于矩形类的练习,可能包含了如何利用继承和多态的概念来设计一个图形类库。通常,我们可能会有一个抽象的`Shape`类作为基类,它包含共享的属性(如颜色)和方法(如获取面积),然后有...

    继承与多态程序演示

    继承是一种设计模式,允许一个类(子类或派生类)从另一个类(父类或基类)获取属性和方法。这种机制使得子类可以复用父类的功能,并在其基础上进行扩展或定制。在MFC框架中,我们可以创建一个CShape类作为基本形状...

    Java实验报告——类的继承、多态的应用

    在`main`方法中,我们创建了`UnderGraduate`和`Graduate`的对象,并通过`StudentManager`进行操作,显示了不同类型的“学生”对象可以被同一个方法处理,这就是多态的直观表现。 总结来说,这个实验报告通过实际...

Global site tag (gtag.js) - Google Analytics