覆写
方法覆写
子类与父类一旦产生了继承关系之后,实际上子类会继承父类中的全部定义,但是这里面也有可能出现不合适的场景。如果发现父类中设计不足并且需要保留有父类中的方法或者属性名称的情况下就会发生覆写。
当子类定义了与父类方法名称相同,参数类型及个数完全相同的时候,就称为方法的覆写。
class Channel{
public void connect(){
System.out.println("[父类]进行资源的连接");
}
}
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();
}
}
由于现在实例化的是子类(DatabaseChannel)对象,所以此时调用的方法一定是被子类所覆写过的方法,如果该方法没有被覆写过,那么将调用父类中提供的方法,覆写的意义是在于:优化父类的功能。
在子类进行方法覆写之后如果现在要想继续调用父类中的方法,那么就必须使用“super.方法()”。
class Channel{
public void connect(){
System.out.println("[父类]进行资源的连接");
}
}
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();
}
}
方法覆写限制
虽然利用方法的覆写可以更好的扩充父类的功能,但是对于覆写也是其自身要求的:
被覆写的方法不能拥有比父类方法更严格的访问控制权限(public>protected>default>private)
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:- 类、接口、变量、方法。
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
//错误的覆写
class Channel{
public void connect(){
System.out.println("[父类]进行资源的连接");
}
}
class DataBaseChannel extends Channel{
void connect(){//访问控制权小于父类
super.connect();
System.out.println("[子类]进行资源的连接");
}
}
public class JavaDemo{
public static void main(String args[]){
DataBaseChannel channel = new DataBaseChannel();
channel.connect();
}
}
重载(overloading)和覆写(overriding)之间的区别:
- 重载(overloading)是指同一个函数的不同版本之间参数不同,重载可以有函数重载和运算符重载。
- 覆写(overriding)是指子类改写父类的方法或称重写,覆盖。
(1)重载
重载是编写一个与已有函数同名但参数列表不同(参数类型或参数个数不同)的方法,具有以下特征: - 方法名必须相同
- 参数列表必须不同,与参数列表的顺序无关
返回值类型可以不同,但就两个函数的返回值而言,不足以区分两个函数是否重载。
(2)覆写
覆写是派生类重写基类的虚函数;具有以下特征: - 只有虚函数和抽象方法才能够被覆写
- 具有相同的函数名
- 具有相同的参数列表
- 具有相同的返回值类型
(3)重载是一种语法规则,是由编译器在编译阶段完成,不属于面向对象编程;而覆写是由运行阶段决定的,是面向对象编程的重要特征。
属性覆盖
当子类定义了与父类相同名称的成员时候就称为属性覆盖。
class Channel{
String info = "www.baidu.com";
}
class DataBaseChannel extends Channel{
String info = "Hello World";//名称相同
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();
}
}
如果说这个时候按照标准的开发属性进行了封装,这时候实际上子类就和父类中的私有属性没有什么关系了,即使名称一样,也只是相当于子类定义了一个新的属性而已。
class Channel{
String info = "www.baidu.com";
public String getInfo(){
return this.info();
}
}
class DataBaseChannel extends Channel{
String info = "Hello World";//名称相同
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:
- 在程序类中使用this表示先从本类查找所需要的属性或方法,如果本类不存在则查找父类定义,如果使用super则表示不查找子类,直接查找父类;
- this 与 super都可以进行构造方法的调用,但是 this()调用的是本类构造,而super()是由子类调用父类构造,两个语句都必须放在构造方法的首行,所以不能够同时出现;
- this表示当前对象,super表示父类对象
final关键字
final在程序之中描述的是种终接器的概念,在java里面final使用关键字可以实现如下的功能:定义不能够被继承的类、定义不能被覆写的方法、常量。
final class Channel{}//这个不能有子类
class DatabaseChannel extends Channel{}//错误的
public calss JavaDemo{
public static void main(String args[]){
}
}
当子类继承了父类之后实际上是可以进行父类中方法覆写的,但是如果你现在不希望子类覆写,用final来进行定义。
class Channel{
public final void connect(){}//不能被覆写
}
class DatabaseChannel extends Channel{
public void connect(){}//错误的
}
public calss JavaDemo{
public static void main(String args[]){
}
}
在有一些系统开发之中,可能使用1表示开关打开、使用0表示开关关闭,但是如果说现在要是直接操作0或者是1,则会造成混乱,所以就希望可以通过一些名称来表示0或者是1。在final关键字里面有一个重要的应用技术:可以利用其定义常量,常量的内容一旦定义则不可修改。
class Channel{
private final int ON=1;//ON就是常量
private final int OFF = 0;//OFF就是常量
public final void connect(){
ON = 2;//错误
}
}
public calss JavaDemo{
public static void main(String args[]){
}
}
实际上常量往往都是公共的定义,所以为了可以体现出共享的概念,往往会使用一种全局常量的形式来定义,使用public static final
来定义全局常量。在定义全局常量的时候每一个字母必须大写表示。
private static final int ON = 1;//ON就是常量
private static final int OFF = 0;//OFF就是常量