- 关键字 : extends
- extends表明正在构造的新类派生于一个已经存在的类, 这个已经存在的类称为
超类
基类
或父类
; 新类称为子类
或孩子类
- 从某个特定的类到其祖先的路径称为该类的继承链
在java中, 继承有三个特征 :
- JAVA是单继承的, 一个类的直接父类只能有一个
class A extends B{} // 正确
class A extends B,C{} // 错误
- JAVA语言可以多级继承 ( java.lang.Object类是继承链的顶端 )
class A extends B{} // 正确
class B extends C{} // 正确
- 一个子类的直接父类是唯一的, 但是一个父类可以拥有很多个子类
多态
在java中, 对象变量是多态的, 子类的每个对象也是超类的对象 e.g. 一个Employee类型的变量既可以引用一个Employee类型的对象, 也可以引用Employee类的任何一个子类的对象 ( 例如, Manager, Executive, Secretary等 )
关于多态中的成员变量
- 直接访问成员变量 : 看等号左边是谁, 则优先用谁, 如果没有就向上查找, 不会向下查找 : e.g.
public class Father { // 父类
int x = 10;
}
public class Son extends Father { // 子类
int x = 20;
}
public class MainFunc {
public static void main(String[] args) {
Father obj = new Son(); // 多态
System.out.println(obj.x);
}
}
输出为10, 也就是父类的x属性
" 编译看左边, 运行也看左边 "
- 如果用成员方法间接访问成员变量, 则方法属于谁就优先用谁, 如果没有就向上查找.
关于多态中的成员方法
成员方法的访问原则 :
看new的是谁, 就优先用谁, 如果没有就向上查找
Father obj = new Son();
obj.method; // 父类子类都有, 优先使用子类的
obj.method_of_father; // 子类没有, 向上查找使用父类
obj.method_of_son; // 父类没有, 报错 ! (编译不通过)
" 编译看左边, 运行看右边 "
使用多态的好处
比如一个学校里有很多不同的工种 教授, 副教授, 导员, 讲师, 助教.... 他们都是为学校工作
他们在学校都是工作, 那么不使用多态的写法为 :
teacher a = new teacher();
assistant b = new assistant();
professor c = new professor();
a.work();
b.work();
c.work();
....
使用多态则为 :
Employee a = new teacher();
Employee b = new assistant();
Employee c = new professor();
...
无论右边是什么, 左边对于学校来说都是Employee的身份...
- 关于强制类型转换 ( 向下转型 ) :
- 只能在继承层次内进行强制类型转换
- 在将超类强制转换成子类之前, 应该用instanceof进行检查
if ( a instanceof b) {
c = (b) a;
}
super关键字
- 在子类的成员方法中, 访问父类的成员变量
- 在子类的成员方法中, 访问父类的成员方法
- 在子类的构造方法中, 访问父类的构造方法
public son extends father{
int num = 20;
public son() {
super(); // 父类的构造方法
}
public void methodson() {
sout(super.num); // 父类的num
}
public void method() {
super.method(); // 父类的method
}
}
抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
抽象类和抽象方法用abstract关键字表示
public abstract class Animal {
// 抽象方法
public abstract void eat();
// 普通的成员方法
public void normalMethod() {
}
}
子类必须覆盖重写抽象类的所有抽象方法 : ( idea中在子类 alt + enter -- implement -- @Override)
- 一个继承的案例 : 发红包
User父类 :
package Red_Beg;
public class USer {
private String name;
private int money;
// alt + insert自动生成
public USer() {
}
public USer(String name, int money) {
this.name = name;
this.money = money;
}
public void show() {
System.out.println("我叫, " + name + ", 我有多少钱? : " + money);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
Manager发红包 :
package Red_Beg;
import java.util.ArrayList;
public class Manager extends USer {
public Manager() {
}
public Manager(String name, int money) {
super(name, money);
}
public ArrayList<Integer> send(int totalMoney, int count) {
// 集合, 存储若干个红包的金额
ArrayList<Integer> redList = new ArrayList<>();
int leftMoney = super.getMoney();
if (totalMoney > leftMoney) {
System.out.println("余额不足");
return redList;
} else // 扣钱
{
super.setMoney(leftMoney - totalMoney);
// 发红包平均拆分成count段
int avg = totalMoney / count;
int mod = totalMoney % count;
// 放进集合
for (int i = 0; i < count - 1; i++) {
redList.add(avg);
}
int last = avg + mod;
redList.add(last);
return redList;
}
}
}
Member收红包 :
package Red_Beg;
import java.util.ArrayList;
import java.util.Random;
public class Member extends USer {
public Member() {
}
public Member(String name, int money) {
super(name, money);
}
public void receive(ArrayList<Integer> list) {
// 随机抽取一个红包
int index = new Random().nextInt(list.size());
// 以上为生成一个0-list.size()的随机int
// 根据索引从集合中删除
int delta = list.remove(index);
int money = super.getMoney();
super.setMoney(money + delta);
}
}