1、本次的预计讲解的知识
1、方法的覆写;
2、属性的覆盖。
2、具体内容
继承性的主要特征是子类可以根据父类也有的功能进行功能的扩展,但是在子类在定义属性或方法的时候有可能的属性和方法与父类同名,那么在这样的情况下就称为覆写。
2.1、方法的覆写(重点)
当子类定义了与父类方法名称相同、参数的类型及个数、返回值相同的方法时就成为发生了覆写。
范例:观察覆写的产生效果
class A{ public void fun() { System.out.println("A类中的fun()方法") ; } } class B extends A{
} public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; } } |
因为这个时候子类并没有fun()方法,所以这个时候子类使用fun()方法时会直接使用A类继承而来的fun方法。
范例:观察覆写
class A{ public void fun() { System.out.println("A类中的fun()方法") ; } } class B extends A{ public void fun() { System.out.println("B类中的fun()方法") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; } } |
当发生了覆写之后,此时会调用实例化子类中已经被覆写的方法。
一个类可能会产生多个子类,那么每一个子类都一定会有自己的实现。
class A{ public void fun() { System.out.println("A类中的fun()方法") ; } } class B extends A{ public void fun() { System.out.println("B类中的fun()方法") ; } } class C extends A{ public void fun() { System.out.println("C类中的fun()方法") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; C c = new C() ; c.fun() ; } } |
覆写结果的分析要素:
·观察实例化的是哪个类;
·观察这个实例化的类里面调用的方法是否是已经覆写过的,如果没覆写过调用父类的。
覆写的使用原则(被动)
·如果现在父类中的方法名称功能不足(不适合与本子类),但是又必须使用这个方法名称的时候,就需要采用覆写这一概念实现。
以上的代码的确已经实现了覆写的工功能,但是如果要想更好的操作,还必须考虑权限问题,被子类所覆写的方法不能够用比父类更严格的访问控制权限。
对于访问控制权限已经学习过三个:public>default>private,也就是说private的访问权限是最严格的。即:如果父类的方法使用的是public声明,那么子类覆写此方法的时候只能是public,如果父类的方法是default的话,那么子类覆写此方法的时候只能够使用default或public。99%的情况下只要是方法都是用public声明。
范例:正确的覆写
class A{ void fun() { System.out.println("A类中的fun()方法") ; } } class B extends A{ public void fun() { System.out.println("B类中的fun()方法") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; } } |
范例:错误的覆写
class A{ public void fun() { System.out.println("A类中的fun()方法") ; } } class B extends A{ void fun() { System.out.println("B类中的fun()方法") ; } } |
此时子类中使用了default权限,将对于父类中public权限属于更加严格的范畴。
疑问?如果父类中方法使用了private声明,子类中方法使用public声明,那么叫覆写吗?
从概念上来讲,父类的方法private,属于小范围权限,而public属于扩大范围的权限。权限上符合覆写要求。
下面先抛开private不看,先使用一个正常的覆写操作
class A{ public void fun() { print() ; } public void print() { System.out.println("大家下午好") ; } } class B extends A{ public void print() {//覆写的print()方法 System.out.println("下午好") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; //下午好 } } |
下面使用private声明父类中的方法
class A{ public void fun() { print() ; } private void print() { System.out.println("大家下午好") ; } } class B extends A{ public void print() {//覆写的print()方法 System.out.println("下午好") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.fun() ; //大家下午好 } } |
这个时候发现子类中根本就没有覆写print()方法,也就是说如果使用private声明这个方法对于子类是不了见的,就算子类定义了一个与之完全相同的符合与覆写要求的方法,那么也不能够发生覆写。这个时候子类所写的方法实际上就相当于子类自己定义了的一个新方法而已。
一旦有了覆写之后发现,默认情况下子类所能够掉用的一定是覆写过的方法。为了能够明确的由子类调用父类中已经被覆写的方法,那么可以使用“super . 方法()”类进行访问。
class A{ public void print() { System.out.println("大家下午好") ; } } class B extends A{ public void print() {//覆写的print()方法 super.print() ; System.out.println("下午好") ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.print() ; } } |
关于super.方法()与this.方法()区别?
使用的“this.方法()”会首先查找本类是否有要掉用的方法名称,如果存在将直接调用,如果不存在则查找父类中的方法是否具备有此方法,如果有就掉用,如果没有将会发生编译时的错误。
使用“super.方法()”,明确的表示调用的不是子类的方法(不查找子类是否有此方法)、而直接调用父类中的指定方法。
面试题:请解释重载与覆写的区别?(请解释Overloading与Overrid的区别?)
在使用Overloading的时候返回值能否不同?
No. | 区别 | 重载 | 重写 |
1 | 英文 | Overloading | Overrid |
2 | 发生范围 | 发生在一个类里面 | 发生在继承关系中 |
3 | 定义 | 方法名称相同、参数的类型及个数相同 | 方法名称相同、参数的类型、个数相同、方法返回值相同 |
4 | 权限 | 没有权限的限制 | 被覆写的方法不能拥有比父类更为严格的访问控制权限 |
在发生重载关系的时候,返回值可以不同,但是考虑到程序设计的统一性,重载时尽量保证方法的返回值类型相同。
2.2、属性的覆盖(了解)
如果说现在子类定义了完全相同的属性名称,就称为属性的覆盖。
范例:观察属性覆盖
class A{ String info = "hello" ; } class B extends A{ int info = 100 ;//名称相同 public void print() { System.out.println(super.info) ; System.out.println(this.info) ; } } public class TextDemo { public static void main(String[] args) { B b = new B() ; b.print() ; } } |
一直强调,在任何开发之中,类中的属性必须封装(99%),那么一旦封装之后这样的覆盖是没有任何意义的,因为父类定义的私有属性子类根本看不见,更不会互相影响了。
比较:关于super与this的区别?
No. | 区别 | this | super |
1 | 功能 | 调用本类构造、本类方法、本类属性 | 子类调用父类构造、父类方法、父类属性 |
2 | 操作的形式 | 先查找本类中是否存在有指定的调用结构,如果有则直接调用,如果没有则调用父类定义 | 不查找子类直接调用父类操作 |
3 | 当前对象 | 表示本类的当前对象 | ----- |
在以后的开发之中,对于本类或者是父类的操作,强烈建议加上“this.”或者是“super.”,这样好区分。
3、总结
1、只要发生了继承关系,那么就一定会存在覆写的应用,覆写的应用主要以方法为主;
2、如果现在子类使用父类指定的方法,但是发现父类的方法实现不能够满足此类要求的时候就要使用覆写来完善此类的功能,同时保留父类的方法名称;
3、被子类覆写的方法不能拥有比父类更难为严格的访问你控制权限。