覆写
1:问题的引出
继承的发生的时候,子类会继承父类中的全部定义,但是又可能出现不合适的场景,子类中发现父类中的设计不足且需要保留有父类中的方法或者属性的时候就会发生(用到)覆写。
2:什么是覆写
当子类定义了与父类方法名称相同,参数类型及个数完全相同(跟父类方法一模一样)的时候,成为方法的覆写。
class Channel {
public void connect() {
System.out.println("【Channel父类】进行资源的连接。") ;
}
}
class DatabaseChannel extends Channel { // 要进行数据库连接
public void connect() { // 保留已有的方法名称,而后进行覆写
System.out.println("【子类】进行数据库资源的连接。") ;
}
}
public class JavaDemo {
public static void main(String args[]) {
DatabaseChannel channel = new DatabaseChannel() ;
channel.connect() ;
}
}
//由于现在实例化的子类是子类对象,所以此时调用的方法一定是被子类覆写过的方法,如果该方法没有被覆写过,那么将调用父类中提供的方法
覆写的意义:优化父类的方法。(描述如下图所示)
3覆写父类方法后如何继续调用父类中被覆写的方法
当子类进行方法覆写后如果现在想继续调用父类中的方法,那么就必须使用“super.方法()”。
class Channel {
public void connect() {
System.out.println("【Channel父类】进行资源的连接。") ;
}
}
class DatabaseChannel extends Channel { // 要进行数据库连接
public void connect() { // 保留已有的方法名称,而后进行覆写
super.connect() ; // 直接调用父类中的方法
System.out.println("【子类】进行数据库资源的连接。") ;
}
}
public class JavaDemo {
public static void main(String args[]) {
DatabaseChannel channel = new DatabaseChannel() ;
channel.connect() ;
}
}
//只要在子类中调用父类的方法的时候就一定要在方法前追加有super.方法();
4:方法覆写的限制
虽然利用方法的覆写可以更好的扩充父类的功能,但是对于覆写也有其自身要求:被覆写的方法不能拥有比父类方法更加严格的访问控制权限。
对于访问控制权限: public > default(不写) > private
如果父类中的方法使用了default权限定义,那么子类定义该方法的时候自能够使用public或default定义;
如果父类中的方法使用了public定义,那么子类中的方法只能够使用public定义。
下面是关于private 的一个特例:
class Channel {
private void connect() {
System.out.println("【Channel父类】进行资源的连接。") ;
}
public void fun() {
this.connect() ; // 调用本类方法
}
}
class DatabaseChannel extends Channel { // 要进行数据库连接
// 此时并不是一个覆写,因为父类的connect()方法不可见,那么这个方法对于子类而言就相当于是一个新定义的方法
public void connect() {
System.out.println("【子类】进行数据库资源的连接。") ;
}
}
public class JavaDemo {
public static void main(String args[]) {
DatabaseChannel channel = new DatabaseChannel() ;
channel.fun() ;
}
}
//这个时候子类中的方法就不是覆写,而是定义了一个新的方法
总结:以后的实际开发中定义的方法,95%情况下都是使用public,所以覆写的时候最好考虑public。
面试题:请解释Overloading(重载)和Override(覆写) 的区别?
答:
1:重载:方法名称相同,参数的类型及个数不同;覆写:方法名称,参数类型及个数,返回值相同。
2:重载:没有权限限制;覆写:被覆写方法不能拥有更严格的控制效果。
3:重载发生在一个类之中,覆写发生在继承关系之中。
5:观察属性的覆盖
当子类定义了与父类相同名称的成员时候称为:属性覆盖。
//属性覆盖案例
class Channel {
String info = "www.mldn.cn" ;
}
class DatabaseChannel extends Channel { // 要进行数据库连接
String info = "HelloMLDN" ; // 名称相同
public void fun() {
System.out.println(super.info) ;
System.out.println(this.info) ;
}
}
public class JavaDemo {
public static void main(String args[]) {
DatabaseChannel channel = new DatabaseChannel() ;
channel.fun() ;
}
}
如果说这个时候按照标准的开发属性进行了封装,这个时候实际上子类和父类中的私有属性就没有什么关系了,即便名称一样,也是相当于子类定义了一个新的属性而已。
lass Channel {
private String info = "www.mldn.cn" ;
public String getInfo() {
return this.info ;
}
}
class DatabaseChannel extends Channel { // 要进行数据库连接
String info = "HelloMLDN" ; // 名称相同
public void fun() {
System.out.println(this.info) ;
System.out.println(super.getInfo()) ;
}
}
public class JavaDemo {
public static void main(String args[]) {
DatabaseChannel channel = new DatabaseChannel() ;
channel.fun() ;
}
}
面试题:请结束super和this的区别:
1:在程序中使用this表示从本类中查找所需要的属性或者方法,如果本类中不存在则查找父类;如果使用了super则表示不查找子类,直接查找父类;
2:this和super都可以及逆行构造方法的调用,但是this()调用的是本类构造,而super 是由子类调用父类构造,两个都必须放在构造方法的首行;
3:this可以表示当前对象。