13 | 继承和多态:面向对象运行期的动态特性
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
面向对象编程的继承和多态是面向对象语言的重要特性。继承使子类自动具备父类的属性和方法,实现了代码的重用,而多态则允许不同子类在调用相同方法时执行不同的动作,提供了灵活性和统一的使用方式。本文从类型体系的角度解释了继承和多态的概念,并介绍了子类型的概念,即子类型 is a 父类型,并探讨了子类型的实现方式。此外,文章还讨论了在编译期对继承和多态特性进行语义分析的挑战,以及在运行期实现方法的动态绑定的问题。通过本文,读者可以快速了解面向对象编程中继承和多态的重要性,以及相关的语义分析和动态绑定的技术特点。文章还介绍了在运行期实现方法的动态绑定的原理,以及继承情况下对象的实例化过程。最后,通过一个示例程序,深入讲解了this和super的语义和使用方法。整体而言,本文通过深入浅出的方式,帮助读者全面理解了面向对象编程中继承和多态的重要概念,以及相关的技术特点。
《编译原理之美》,新⼈⾸单¥59
全部留言(17)
- 最新
- 精选
- 曾经瘦过看到了评论 泛型 然后想到了反射。根据使用经验(反射报错都是在运行时),老师在后端的部分会讲一下反射吗?
作者回复: 我看看在讲Java那讲里能否把这个内容兼顾。 有同学提的泛型,其实我还没有安排进去...实在不行做个加餐。 这里先提一句:java的泛型其实只是语法糖,是在基础语法的基础上封装了一层而已。运行期,带泛型和不带泛型的,是完全同一套代码,没区别。LinkedList<String>和LinkedList<Object>运行时没区别。只是在编译期添加了额外的类型检查功能。 这跟C++的模板完全不是一回事。
2019-09-27213 - Gopher老师能增加一讲泛型吗?这样就圆满了🤣
作者回复: 好的,我把这个问题在答疑那讲里作为一个点。
2019-09-157 - 影影影老师您好,有些小的疑惑,麻烦解答下。 对于文中提到的,在ThisSuperTest.java类中调用Mammal的构造方法Mammal(int weight)后调用this.speak()这个例子。 根据您的解释,是会调用Cow类的speak函数。其中您也提到了,在调用这个方法时,Cow类初始化并没有开始。 因此我的疑惑是,在一个类(Cow)的实例没有初始化的时候,为何就已经可以去调用这个实例的方法了?
作者回复: Java语言的成员变量,只要给它分配了内存空间,就一定会做初始化。所以,即使还没有运行这个类的构造方法,其实这些变量也都可以用了,只不过里面的是缺省值。 Java只所以采取这个机制,可能就是跟面向对象的生存期特征有关的。也就是,所有成员变量要在调用任何方法之前就创建,并且可用。所以,这个时候调用方法并没有问题。 所以,Cow类的初始化过程,如果用放大镜看的话,可能会分成多个阶段。对于int a = 10;这样一个语句来说: 阶段1:Cow及其父类的成员属性都获得了内存,并具备了缺省值。 阶段2:使用变量声明时的初始化部分,让a的值变为10; 在这个阶段,其实还可以用int a = b;或者int a = foo()这样的方式来做初始化,这时候要求b一定是在a的前面。 阶段3:运行自定义的构造函数。这时候,a的值可能又被修改成其他值。
2019-09-1344 - xiaobangJava里面构造函数里面居然允许多态,感觉行为怪怪的,不符合自觉。另外ThisSuperTest里面那个weihgt和speak 前面不加this 语义也一样吗
作者回复: 允许多态正常,因为虽然是在构造函数中,但已经要使用对象的方法了,所以多态逻辑就会发生作用。 不过,java对象的初始化的语法设计,似乎还可以做得更好。比如,如果调用super(),必须出现在第一行等等。需要明白初始化的原理,才会理解为什么这么设计。 另,你的问题:加不加this都是一样的。
2019-09-1723 - 林恒杰现在深度学习的端侧芯片碎片化比较严重,因而对于编译器需求也开始变多起来,包括谷歌最近也像LLVM社区提交了MLIR,老师可以讲一下这个部分的看法吗?
作者回复: 好的,我安排在后端部分会讨论一下这个问题。 深度学习发展速度太快。从长远来看,需要标准的IR。这又是一次标准之争。
2019-09-113 - 李懂也就是只有方法存在多态,属性和构造函数是不存在多态! 这个this,super是咋实现的,以前觉得this是当前对象 super是父类对象,现在看来好像不对!
作者回复: 总的来说,this和super在三个场景中,它的语义是有差别的。 场景1:对象属性:适用原理,是变量作用域。 场景2:对象方法:适用原理,是多态; 场景3:构造方法。这个只是长得像方法,其实不是方法。要用对象初始化的逻辑去分析它。 this和super的实现,你可以参考一下playscript-java的代码。 另外,可以再像ThisSuperTest.java一样,写点代码深入测试一下this和super特性。
2019-09-1123 - 余晓飞// 在本级查找这个这个方法 Function rtn = super.getFunction(name, paramTypes); 这里需要首先在本级查找,但是根据下文介绍的super特性,这里查找的应该是上级及以上的方法,是在这里和Java有差别吗?
作者回复: 抱歉回复晚了。 方法的overide,是下级覆盖商机,所以应该先从下级查找。如果下级实现了,就用下级的。 如果下级没有,就用上级的,这就是inheritence。
2019-09-2222 - cry soul还有一个点,其实比较想知道的是多线程的实现。以及线程安全问题等,怎么样实现是原子级的操作。希望老师能稍微提及这样的内容,因为本身是做web开发的,真的比较好奇。
作者回复: 线程的原理,是操作系统的内容,你可能要去那门课程多学一下:) 过去的语言(如C语言),只是提供标准的库,让你访问操作系统的线程管理功能,包括信号量、同步互斥什么的。 Java语言增加了一些专门处理多线程的元素,比如synchronized关键字。 go语言又更进一步,把操作系统的线程进行了封装,变成了轻量级的goroutine,很受欢迎。
2019-10-1131 - 沉淀的梦想看代码的时候有个疑问,this作为一个primary,当要去找其左值的时候,会去各个作用域中搜索thisRef,但是thisRef是什么时候加入到作用域的符号表的呢?没有找到代码中对应的位置
作者回复: 在RefResolver.exitPrimary()中,在这里做与primary有关的引用消解。 This variable = theClass.getThis(); at.symbolOfNode.put(ctx, variable);
2019-09-131 - 沉淀的梦想看老师的代码里好像没有对类方法和对象方法进行区分,是因为PlayScript目前还不支持类方法吗?
作者回复: 对,目前没有支持类方法。也没有支持类级别的成员变量。
2019-09-131