面向对象三大特性之继承性
面向对象的三大特征:封装、继承、多态
继承是多态的前提,如果没有继承,就没有多态。
在继承的关系中,”子类就是一个父类“。也就是说,子类可以被当作父类看待。
例如父类是员工,子类是讲师,那么”讲师就是一个员工“。
Java语言是单继承的。一个类的直接父类只能由唯一一个。
但是,Java语言可以多级继承。
一个子类的直接父类是唯一的,但是一个父类可以由多个子类。
16.1 继承的基本格式
定义父类格式:(一个普通的类定义)
定义子类的格式:
1 2 3
| public class 子类名称 extends 父类名称{
}
|
Employee类
1 2 3 4 5 6 7 8
| package com.tipdm.demo01;
public class Employee { public void method(){ System.out.println("方法执行!"); } }
|
Teacher类
1 2 3 4 5
| package com.tipdm.demo01;
public class Teacher extends Employee{ }
|
Assistant类
1 2 3 4 5
| package com.tipdm.demo01;
public class Assistant extends Employee{ }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.tipdm.demo01;
public class demo1 { public static void main(String[] args) { Teacher teacher1 = new Teacher(); teacher1.method();
Assistant assistant1 = new Assistant(); assistant1.method(); } }
|
1 2 3 4
| 方法执行! 方法执行!
进程已结束,退出代码0
|
继承后的特点
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类对象访问成员变量:
间接通过成员方法访问成员变量:
父类
1 2 3 4 5 6 7 8 9 10 11
| package com.tipdm.demo02;
public class Fu { int numFu = 10; int num = 100;
public void methodFu(){ System.out.println(num); } }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.tipdm.demo02;
public class Zi extends Fu{ int numZi = 20;
int num = 200;
public void methodZi(){ System.out.println(num); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.tipdm.demo02;
public class demo1 { public static void main(String[] args) { Fu fu = new Fu(); System.out.println(fu.numFu);
System.out.println("================"); Zi zi = new Zi(); System.out.println(zi.numFu); System.out.println(zi.numZi); System.out.println("================");
System.out.println(zi.num);
System.out.println("================");
zi.methodZi(); zi.methodFu(); } }
|
1 2 3 4 5 6 7 8 9 10 11
| 10 ================ 10 20 ================ 200 ================ 200 100
进程已结束,退出代码0
|
继承后变量的访问规则
父类
1 2 3 4 5
| package com.tipdm.demo03;
public class Fu { int num = 10; }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.tipdm.demo03;
public class Zi extends Fu{ int num = 20;
public void method(){ int num = 30; System.out.println(num); System.out.println(this.num); System.out.println(super.num); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.tipdm.demo03;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi();
zi.method(); } }
|
继承后方法的访问规则
在父子类的继承关系中,创建子类对象,访问成员方法的规则:
注意事项:
- 无论是成员方法还是成员变量,如果没有都是向上找父类,绝不会向下找子类的。
重写(Override)概念:在继承关系中,当方法的名称一样,参数列表也一样。
重写(Overrie): 方法的名称【一样】,参数列表【也一样】。覆盖、覆写。
重载(Overload): 方法的名称【一样】,参数列表【不一样】。
- 方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。
父类
1 2 3 4 5 6 7 8 9 10 11
| package com.tipdm.demo04;
public class Fu { public void methodFu(){ System.out.println("父类方法执行!"); }
public void method(){ System.out.println("父类重名方法执行!"); } }
|
子类
1 2 3 4 5 6 7 8 9 10 11
| package com.tipdm.demo04;
public class Zi extends Fu{ public void methodZi(){ System.out.println("子类方法执行!"); }
public void method(){ System.out.println("子类重名方法执行!"); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.tipdm.demo04;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi();
zi.methodFu(); zi.methodZi();
zi.method(); }
}
|
1 2 3 4 5
| 父类方法执行! 子类方法执行! 子类重名方法执行!
进程已结束,退出代码0
|
继承之重写(Override)
父类
1 2 3 4 5 6 7
| package com.tipdm.demo05;
public class Fu { public void method(){ System.out.println("父类方法!"); } }
|
子类
1 2 3 4 5 6 7 8
| package com.tipdm.demo05;
public class Zi extends Fu{ @Override public void method(){ System.out.println("子类方法!"); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.tipdm.demo05;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi(); zi.method(); } }
|
复用父类的方法
父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm.demo06;
public class Phone { public void call(){ System.out.println("打电话!"); }
public void send(){ System.out.println("发短信!"); }
public void show(){ System.out.println("显示号码"); } }
|
子类
1 2 3 4 5 6 7 8 9 10 11
| package com.tipdm.demo06;
public class NewPhone extends Phone{ @Override public void show() { super.show(); System.out.println("显示姓名"); System.out.println("显示头像"); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm.demo06;
public class demo1 { public static void main(String[] args) { Phone phone = new Phone(); phone.call(); phone.send(); phone.show(); System.out.println("==============");
NewPhone newPhone = new NewPhone(); newPhone.call(); newPhone.send(); newPhone.show(); } }
|
1 2 3 4 5 6 7 8 9 10 11
| 打电话! 发短信! 显示号码 ============== 打电话! 发短信! 显示号码 显示姓名 显示头像
进程已结束,退出代码0
|
父子类构造方法访问特点
父类
1 2 3 4 5 6 7 8 9 10
| package com.tipdm.demo07;
public class Fu { public Fu(){ System.out.println("父类无参构造方法"); } public Fu(int num){ System.out.println("父类有参构造方法"); } }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.tipdm.demo07;
public class Zi extends Fu{ public Zi(){ super(); System.out.println("子类构造方法!"); }
}
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm.demo07;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi(); } }
|
1 2 3 4
| 父类无参构造方法 子类构造方法!
进程已结束,退出代码0
|
super关键字的三种用法
super关键字的用法有三种:
- 在子类的成员方法中,访问父类的成员变量
- 在子类的成员方法中,访问父类的成员方法
- 在子类的构造方法中,访问父类的构造方法
父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm.demo08;
public class Fu { int num = 10;
public Fu(){ System.out.println("父类的无参构造方法!"); } public Fu(int num){ System.out.println("父类的有参构造方法!"); }
public void methodFu(){ System.out.println(num); } }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.tipdm.demo08;
public class Zi extends Fu{ int num = 20;
public Zi(int num){ super(num); }
public void methodZi(){ super.methodFu(); System.out.println(super.num); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.tipdm.demo08;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi(123); System.out.println("============"); zi.methodZi(); } }
|
1 2 3 4 5 6
| 父类的有参构造方法! ============ 10 10
进程已结束,退出代码0
|
this关键字的三种用法
super关键字用来访问父类内容,而this关键字用来访问本类内容。用法也有三种:
- 在本类的成员方法中,访问本类的成员变量。
- 在本类的成员方法中,访问本类中的另一个成员方法。
- 在本类的构造方法中,访问本类中的另一个构造方法。
在第三种用法当中要注意:
- A. this(…)调用也必须是构造方法的第一个语句,唯一一个。
- B. this和super只能一个放在构造方法的第一个语句。
父类
1 2 3 4 5
| package com.tipdm.demo09;
public class Fu { int num = 30; }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.tipdm.demo09;
public class Zi extends Fu{ int num = 20;
public Zi(){
this(123);
}
public Zi(int n){ this(12, 13); }
public Zi(int m, int n){}
public void method(){ int num = 10; System.out.println(num); System.out.println(this.num); System.out.println(super.num);
this.showMessage(); }
public void showMessage(){ System.out.println("本类中的另外一个成员方法!"); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.tipdm.demo09;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi(); zi.method(); } }
|
1 2 3 4 5 6
| 10 20 30 本类中的另外一个成员方法!
进程已结束,退出代码0
|
抽象方法和抽象类
抽象父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.tipdm.demo10;
public abstract class Animal { public abstract void eat(); }
|
子类
1 2 3 4 5 6 7 8
| package com.tipdm.demo10;
public class Cat extends Animal{ @Override public void eat() { System.out.println("吃鱼!"); } }
|
主类
1 2 3 4 5 6 7 8
| package com.tipdm.demo10;
public class demo1 { public static void main(String[] args) { Cat cat1 = new Cat(); cat1.eat(); } }
|
抽象类的构造方法
父类
1 2 3 4 5 6 7 8
| package com.tipdm.demo11;
public abstract class Fu { public Fu(){ System.out.println("抽象父类构造方法执行!"); } public abstract void eat(); }
|
子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.tipdm.demo11;
public class Zi extends Fu{
public Zi(){ System.out.println("子类构造方法执行!"); }
@Override public void eat() { System.out.println("吃饭饭"); } }
|
主类
1 2 3 4 5 6 7 8
| package com.tipdm.demo11;
public class demo1 { public static void main(String[] args) { Zi zi = new Zi(); zi.eat(); } }
|
注意事项:
- 一个抽象类不一定含有抽象方法, 只要保证抽象方法所在的类是抽象类即可.
- 这样没有抽象方法的抽象类,也不能直接创建对象,在一些特殊场景下有用途.
1 2
| public abstract class MuAbstract { }
|
抽象类的继承
父类
1 2 3 4 5 6 7 8
| package com.tipdm.demo12;
public abstract class Animal { public abstract void sleep();
public abstract void eat(); }
|
二级父类
1 2 3 4 5 6 7 8 9 10
| package com.tipdm.demo12;
public abstract class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃骨头"); }
}
|
子类1
1 2 3 4 5 6 7 8
| package com.tipdm.demo12;
public class Dog2ha extends Dog{ @Override public void sleep() { System.out.println("hehehehe~~"); } }
|
子类2
1 2 3 4 5 6 7 8
| package com.tipdm.demo12;
public class DogGolden extends Dog{ @Override public void sleep() { System.out.println("呼呼呼...."); } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm.demo12;
public class demo { public static void main(String[] args) {
Dog2ha dog2ha = new Dog2ha(); dog2ha.eat(); dog2ha.sleep(); System.out.println("================");
DogGolden dogGolden = new DogGolden(); dogGolden.eat(); dogGolden.sleep(); } }
|
1 2 3 4 5 6 7
| 狗吃骨头 hehehehe~~ ================ 狗吃骨头 呼呼呼....
进程已结束,退出代码0
|
题目:群主发红包
群主发普通红包.某群有多名成员,群主给成员发普通红包.
- 普通红包规则:
- 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取.
- 成员领取红包后,保存到成员余额中.
User类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.tipdm.demo13;
public class User { private String name; private int money;
public void show(){ System.out.println("我是:" + this.name + ",我有多少钱:" + this.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; }
public User(String name, int money) { this.name = name; this.money = money; }
public User() { } }
|
Manager类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.tipdm.demo13;
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> RPList = new ArrayList<>(); int restMoney = super.getMoney(); if(totalMoney > restMoney){ System.out.println("余额不足!"); return RPList; } super.setMoney(restMoney - totalMoney); int RP = totalMoney / count; int rest = totalMoney % count; for (int i = 0; i < count - 1; i++) { RPList.add(RP); } RPList.add(RP + rest); return RPList; } }
|
member类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.tipdm.demo13;
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 get(ArrayList<Integer> RPList){ if (RPList.size() == 0){ System.out.println("*红包数量不够,[" + super.getName() + "]未抢到红包!"); }else { int index = new Random().nextInt(RPList.size()); Integer rp = RPList.remove(index); int restMoney = super.getMoney(); super.setMoney(restMoney + rp); } } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.tipdm.demo13;
import java.util.ArrayList;
public class demo1 { public static void main(String[] args) { Manager manager = new Manager("群主", 100); Member member1 = new Member("员工1", 0); Member member2 = new Member("员工2", 0); Member member3 = new Member("员工3", 0); Member member4 = new Member("员工4", 0); manager.show(); member1.show(); member2.show(); member3.show(); member4.show(); System.out.println("=========== 开始发送红包 ==========="); ArrayList<Integer> RPList = manager.send(50, 4); member1.get(RPList); member2.get(RPList); member3.get(RPList); member4.get(RPList); System.out.println("=========== 红包发送结束 ==========="); manager.show(); member1.show(); member2.show(); member3.show(); member4.show(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 我是:群主,我有多少钱:100 我是:员工1,我有多少钱:0 我是:员工2,我有多少钱:0 我是:员工3,我有多少钱:0 我是:员工4,我有多少钱:0 =========== 开始发送红包 =========== =========== 红包发送结束 =========== 我是:群主,我有多少钱:50 我是:员工1,我有多少钱:12 我是:员工2,我有多少钱:14 我是:员工3,我有多少钱:12 我是:员工4,我有多少钱:12
进程已结束,退出代码0
|