继承、抽象类

  • 一、继承
  • 1. 基本概念
  • 2. 继承关系中的成员访问
  • 3. 重写与重载
  • 4. super 与 this
  • 二、抽象类


一、继承

1. 基本概念

继承主要解决的问题是共性抽取。继承是多态的前提,没有继承就没有多态。

继承关系的特点

  1. 子类可以拥有父类的内容
  2. 子类还可以有自己专属的内容
  3. “子类是一个父类”(is a)

Java中的继承

  1. Java是单继承的,一个类的直接继承父类只能有一个
  2. Java支持多级继承,支持孙类继承子类,子类再继承父类,所有的类最终都继承自Object类
  3. 子类有且只能有一个父类,但是父类可以拥有多个子类
  4. 子类会继承父类中所有的非私有属性和方法,子类可以将从父类继承到的方法进行重写(Override)

java 中抽象类的继承 java继承抽象类的属性_抽象类


一个简单的继承示例

public class Animal {		// 父类
    public void shout() {
		System.out.println("叫");
	}
}

class Cat extends Animal {	// 子类
	public void shout() {	// 子类重写模板方法
        System.out.println("喵喵喵~~~");
    }
    public void scratch() {	// 子类的特有方法
        System.out.println("猫爪挠");
    }
}

2. 继承关系中的成员访问

在继承关系中,如果成员变量重名,子类对象内部的访问规则:

  1. 直接通过子类对象访问成员变量:等号左边是谁就优先用谁,没有则向上找
  2. 间接通过成员方法访问成员变量:方法属于谁,就优先用谁,没有则向上找

通常为了避免歧义,使用 this 和 super 区分成员变量和父类变量

  • 局部变量:直接写变量名
  • 内部成员变量:this.变量名
  • 父类继承变量:super.变量名
System.out.println(num);			// 局部变量
	System.out.println(this.num);		// 成员变量
	System.out.println(super.num);		// 继承变量

3. 重写与重载

重写(Override):在继承关系中,方法名一样,参数列表也一样
重载(Overload):在同一个类中,方法名一样,参数列表不一样

关于关于重写的一些注意事项

  1. 必须保证父子类之间的方法名称相同,参数列表也相同
    - @Override注解:写在方法前面,用来检测是否是有效的覆盖重写。只是一个安全检测手段,非必须。
  2. 子类方法的返回值类型的范围必须小于等于父类方法的返回值范围
    - java.lang.Object类是Java中所有类的最高父类,例如:java.lang.String就是Object的一个子类
    - Java中,所有的类都默认继承自Object类,所有类的范围均小于等于Object类这意味着,如果一个方法的返回值定义为Object类,该方法能够返回任意对象
  3. 子类方法的权限修饰符必须大于等于父类方法的权限修饰符,实际开发中,父子方法的权限尽量保证权限相同

通过继承实现的程序设计原则:对于已经投入使用的类,尽量不要进行修改。而是定义一个新的类,重复利用其中共性的内容,相同功能中添加额外的内容时通过重写对应的方法来实现

4. super 与 this

super关键字用来访问上一级父类内容,this关键字用来访问本类内容

super关键字的用法:

  • 在子类的成员方法中,访问父类的成员变量
  • 在子类的成员方法中,访问父类的成员方法
  • 在子类的构造方法中,访问父类的构造方法

this关键字的用法:

  • 在本类的成员方法中,访问本类的成员变量
  • 在本类的成员方法中,访问本类的另一个成员方法
  • 在本类的构造方法中,访问本类的另一个构造方法

继承关系中,父子类构造方法具有以下特点

  1. 子类构造方法中有一个默认隐含的 super(); 语句,所以一定是现调用父类的构造方法,后执行子类的构造方法
  2. 子类构造可以通过super关键字来调用父类重载构造
  3. super的父类构造调用必须是子类构造方法的第一个语句

在编写构造方法时需要注意:

  1. this(…) 调用必须是构造方法的第一个且唯一的语句
  2. super 和 this 两种构造方法不能同时使用,否则违背上述规则

二、抽象类

抽象方法:使用 abstract 关键词修饰的方法,抽象方法不做具体定义,所以抽象方法没有代码块。定义好方法头后直接以分号结尾

抽象类:抽象方法所在的类称为抽象类,同样使用 abstract 修饰

如何使用抽象类和抽象方法

  1. 抽象类不可以被实例化(抽象的不能被直接具象化)
  2. 只有完全重写抽象类方法的子类(继承类)可以被实例化
  3. 继承类必须重写抽象类中的所有抽象方法,重写方法时不再用 abstract 修饰
  4. 若继承子类没有重写父类的所有抽象方法,那么该子类必须被 abstract 修饰为一个抽象类,相当于子类具象化了父类提供的部分方法,剩余未重写的方法在孙类、后代类中加以实现或部分实现,依次类推。只有全部重写了所有的抽象方法的后代类才能被实例化。

一个简单的抽象类的示例

public abstract class Animal {
    // 抽象元类模板
    public abstract void shout();
}
class Cat extends Animal {
    // 实际需要实例化的子类
    public void shout() {
        // 子类中必须要重写模板方法
        System.out.println("喵喵喵~~~");
    }
    public void scratch() {
    	// 子类特有的方法
        System.out.println("猫爪挠——咔咔咔~~~");
    }
}

显然,抽象类中不一定包含抽象方法,但是拥有抽象方法的类一定是抽象类。