详解 继承(下)—— super关键字 与 多态
接上篇博文——《详解 继承(上)—— 工具的抽象与分层》
废话不多说,进入正题:
本人在上篇“故弄玄虚”,用super();解决了问题,这是为什么呢?
答曰:子类中所有的构造方法默认都会访问父类中空参数的构造方法
(拓展:由于这个原理,我们今后所做的“工具类”都必须要带上无参构造)
那么,父类没有无参构造方法,子类怎么办?
解决父类没有无参构造的手段:
- 在父类中添加一个无参的构造方法
- 子类通过super去调用父类其他的带参的构造方法
- 子类通过this去调用本类的其他构造方法 (本类其他构造也必须首先访问了父类构造)
那么,现在,本人来讲解一下super吧:
super:
super class 其实就是超类、基类、父类的意思。
在这里本人来提醒一点:
Object类 是 所有类的基类
super有两个严格要求:
- 只能出现在构造方法中;
- 如果有super(),则它必须是构造方法的第一条语句
(所以,super() 和 this() 不能同时出现在同一个构造方法中)
而且,不论我们在 子类 中的构造方法是 无参 还是 带参,在默认情况下,JVM只调用基类的无参构造方法!
我们在上篇博文开头就提到过,我们在“继承”的过程中可以“择优继承”,那么,本人现在就来讲解下,如何“择优继承”:
我们实现这个结果的方法是:方法的覆盖
那么,现在我们对于方法的覆盖进行以下说明:
(1)仅存在于有继承关系的类之间;
(2)子类的方法名名称,参数个数和类型,必须和被覆盖的父类保持一致;
(3)子类的返回值必须和被覆盖的父类保持一致;
(4)子类方法的修饰符不能“低于”被覆盖的分类方法;
(5)若违反了(2),则实质上是方法的重载,并非覆盖
(本人在这里只是为了使同学们能了解后面的代码,仅在这里浅谈覆盖,在本人后续博文中会对于方法的覆盖进行深度讲解)
现在我们来举一个简单有趣的例子:
我们先建立一个包 com.mec.about_override.demo,并在包下建立如下类:
Animal.java:
package com.mec.about_override.demo;
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void cry() {
System.out.println("动物的叫声!");
}
}
Dog.java:
package com.mec.about_override.demo;
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void cry() {
System.out.println("汪汪");
}
}
Demo.java:
package com.mec.about_override.demo;
public class Demo {
public static void main(String[] args) {
Animal animal =new Animal("动物");
animal.cry();
Dog dog = new Dog("二愣子");
dog.cry();
}
}
我们现在来编译一下,结果如下:
可以看出,我们在 Animal类中所编写的 cry() 方法被覆盖了!
多态:
现在,本人来介绍本篇博文的另一个知识点 —— 多态:
多态 —— 某一个事物,在不同时刻表现出来的不同状态
首先,多态是有 条件的:
多态前提:
- 要有继承关系
- 要有覆盖(方法重写)
其实没有也是可以的,但是如果没有这个就没有意义- 要有父类引用指向子类对象
形如:
父 f = new 子();
接下来,本人来讲解一个非常有趣的 知识点:
基类 与 派生类 之间的 强制类型转换:
我们对上面的 Dog类 和 Demo类 做如下修改:
Dog.java:
package com.mec.about_override.demo;
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void cry() {
System.out.println("汪汪");
}
public void dogAction() {
System.out.println("狗子快跑!");
}
}
Demo.java:
package com.mec.about_override.demo;
public class Demo {
public static void main(String[] args) {
Animal animal =new Animal("动物");
animal.cry();
Dog dog = new Dog("二愣子");
dog.cry();
Animal otherAnimal = (Animal) dog;
dog.dogAction();
dog.cry();
}
}
运行结果如下:
现在可能就有同学有疑问了这里的输出结果竟然是“汪汪”而不是“动物的叫声”!
这里对上述问题做出解释:
基类 与 派生类 之间的 强制类型转换 遵循如下原则:
- 对象的类型 约束 对象所能引用的 成员 和 方法,但是,不能更改 成员 和 方法 的本质内容;
- 对于方法,强转不能改变 其所 实际指向 的 代码 的首地址; 对象 的类型 决定 对象 所能引用的 对象和方法 的种类(即:Animal类型); 对象 所能调用的 成员 和 方法 取决于所申请空间的 对象和方法(即:Dog类型);
- 子类对象 可以被强转成 父类类型,但父类对象 不能被强转成 子类类型,因为父类对象中可能不存在子类类型的成员和方法
对于以上的现象,可能同学们在初学时会对子类与基类之间的关系感觉有点头晕。
别怕,在这里,本人还要介绍一个知识点,来辅助我们识别它们之间的关系:
多态中的成员访问特点:
- 成员变量 :
编译看左边,运行看左边。- 构造方法 :
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。- 成员方法 :
编译看左边,运行看右边。- 静态方法 :
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
那么,为什么要存在多态这个机制呢?
多态的好处:
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
详解 继承(下)—— super关键字 与 多态的更多相关文章
- 菜鸟笔记 -- Chapter 6.4.2 详解继承
6.4.2 详解继承 6.4.2.1 继承入门 继承使得程序架构具有一定的弹性,在程序中复用一些已经定义完善的类不仅可以减少软件开发周期,也可以提高软件的可维护性和可扩展性.基本思想是基于某个父类 ...
- C#中的Attribute详解(下)
原文地址:https://blog.csdn.net/xiaouncle/article/details/70229119 C#中的Attribute详解(下) 一.Attribute本质 从上篇里我 ...
- javac命令详解(下)
摘自http://blog.csdn.net/hudashi/article/details/7058999 javac命令详解(下) -ver ...
- NPM使用详解(下)
NPM使用详解(下) *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impo ...
- iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)
本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...
- 详解Linux下swig 3.0.12的手动安装过程
详解Linux下swig 3.0.12的手动安装过程 首先 从http://www.linuxfromscratch.org/blfs/view/cvs/general/swig.html上下载swi ...
- 详解Linux下iptables中的DNAT与SNAT设置(转)
详解Linux下iptables中的DNAT与SNAT设置 这篇文章主要介绍了Linux下iptables中的DNAT与SNAT设置,是Linux网络配置中的基础知识,需要的朋友可以参考下 原文连 ...
- Window下PHP三种运行方式图文详解,window下的php是不是单进程的?
Window下PHP三种运行方式图文详解,window下的php是不是单进程的? PHP运行目前为止主要有三种方式: a.以模块加载的方式运行,初学者可能不容易理解,其实就是将PHP集成到Apache ...
- hadoop2.7之作业提交详解(下)
接着作业提交详解(上)继续写:在上一篇(hadoop2.7之作业提交详解(上))中已经讲到了YARNRunner.submitJob() [WordCount.main() -> Job.wai ...
随机推荐
- 洛谷P1003 铺地毯 模拟
这一题就是一个很普通的模拟,每次输入的时候存储四个角的值 把四个角的横纵坐标存储在一排.然后在倒序遍历一遍,查找的时候就看所要查找的坐标在不在这个范围内,如果找到了就标记一下再输出,如果没有找到就输出 ...
- Mayor's posters POJ - 2528 线段树(离散化处理大数?)
题意:输入t组数据,输入n代表有n块广告牌,按照顺序贴上去,输入左边和右边到达的地方,问贴完以后还有多少块广告牌可以看到(因为有的被完全覆盖了). 思路:很明显就是线段树更改区间,不过这个区间的跨度有 ...
- POJ - 3255 SPFA+邻接表求次短路径
题意:给出m条边 , n个顶点,u [ i ]到v [ i ] 的距离w [ i ],求除了最短路的那条最短的边的长度. 思路:之前有做过相似的题,使用迪杰斯特拉算法求单源最短路径,并且记录路径,枚举 ...
- js 的位运算
api 用途 待更...
- [讲解]网络流最大流dinic算法
网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...
- Matlab——m_map指南(3)——实例
m_map 实例 1. clear all m_proj('ortho','lat', 48,'long',-123');%投影方式,范围 m_coast('patch','r');%红色填充 m_g ...
- 关于java动态代理模式
1. 动态代理 动态代理就是通过代理类是代理类与相关接口不直接发生联系,而在运行期(Runtime)实现动态关联. 动态代理主要用到java.lang.reflect包中的两个类,Invocation ...
- Java并发基础08. 造成HashMap非线程安全的原因
在前面我的一篇总结(6. 线程范围内共享数据)文章中提到,为了数据能在线程范围内使用,我用了 HashMap 来存储不同线程中的数据,key 为当前线程,value 为当前线程中的数据.我取的时候根据 ...
- UITextField - 为正文设置缩进
实现思路: 把UITextField的leftView当做填充位置,这样就实现了文字偏移. 代码: UILabel *label = [[[UILabelalloc] initWithFrame:CG ...
- C语言:const关键字用法
参考博客:https://www.cnblogs.com/bianchengzhuji/p/10335837.html const是constant的简写,是不变的意思.但并不是说它修饰常量,而是说它 ...