学习目标:
- 学会类的继承,会使用super,this关键字;
- 能够创建并使用抽象类。
学习内容:
一、继承
1、父类和子类的定义
- 父类的定义:
标准定义类 - 子类的定义:
public class 子类名 extends 父类名 { // ...; }
2、在父子类的继承关系中,如果成员变量重名,则创建子类对象时,有两种访问方式
- 直接通过子类对象访问成员变量
等号左边是谁(创建的是哪个对象),就优先用谁,没有则向上找 - 间接通过成员方法访问成员变量(在成员方法中访问本类中的成员变量)
该方法属于谁,就优先用谁,没有则向上找
3、局部变量,本类成员变量,父类成员变量三者重名(本类中局部变量所在地本类方法中使用)
- 局部变量:
直接用,就近原则 - 本类成员变量
this.成员变量名 - 父类成员变量名
super.成员变量名
4、方法重写注意事项
- 必须保证父子类之间的名称与参数完全相同
- @override:写在方法前面,用来检验是不是有效的覆盖重写
- 这个注释就算不写,只要满足要求,也是正确的覆盖重写
- 子类方法的返回值必须《小于等于》父类方法的返回值类型
- 小扩展提示:
- java.lang.Object是所有类的公共最高父类
- java.lang.String是Object的子类
- 小扩展提示:
- 子类方法的权限必须 《大于等于》父类方法的权限修饰符
- 小扩展提示:public > protected > (default) > private
- 备注:(default)不是关键字default,而是什么都不写
5、继承方法中,父子类构造方法的访问特点
- 子类构造方法中有一个默认隐含的“super()”调用,所以一定是先执行父类构造方法,在执行子类构造方法
- 子类构造可以通过super调用父类重载构造
super(int num); - super的父类构造函数调用语句不能调用多次,只能被调用一次
6、super关键字的使用
- 在子类方法中使用父类的成员变量
- 在子类方法中使用父类的成员方法
- 在子类的构造方法中调用父类的构造方法
7、this关键字的使用
- 本类的成员方法中,访问本类的成员变量
- 本类的成员方法中,访问本类的另一个成员方法
- 本类的构造方法中,访问本类的另一个构造方法
- 注意:
- this关键字调用也是构造方法中唯一且第一个
- this关键字与super关键字两种构造调用不能同时使用
8、继承的特点
- 单继承,一个子类只能有一个父类
- 多级继承,父类–》子类(父类)–》子类。。。
- 一个父类可以有多个子类
二、抽象方法与抽象类
1、抽象方法与抽象类的定义
- 抽象方法:没有方法体,不确定怎么做。
public abstract void eat(); - 抽象类:直接加上abstract关键字,抽象方法必须在抽象类中
public abstract class Animal{ // ...; }
2、抽象类与抽象方法的使用
- 不能直接创建抽象对象
- 必须用一个子类继承抽象对象
- 子类必须覆盖重写抽象类中的所有抽象方法
覆盖重写(实现):去掉abstract关键字并加上方法体 - 创建子类对象进行使用
学习产出:
1、 简单的继承
package mypackage.day05.demo01;
// 定义一个父类:员工
public class Employee {
public static void method(){
System.out.println("方法执行");
}
}
package mypackage.day05.demo01;
// 定义了员工的另一个子类:助教
public class Assistant extends Employee {
}
package mypackage.day05.demo01;
// 定义了一个员工的子类:讲师
public class Teacher extends Employee {
}
package mypackage.day05.demo01;
/*
在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。
定义父类的格式:(一个普通的类定义)
public class 父类名称 {
// ...
}
定义子类的格式:
public class 子类名称 extends 父类名称 {
// ...
}
*/
public class DemoClass {
public static void main(String[] args) {
Teacher.method();
System.out.println("================");
Assistant.method();
}
}
2、成员变量访问规则演示
package mypackage.day05.demo01;
public class Fu {
int numFu = 10;
int num = 100;
public void printFu(){
// 使用的是本类当中的,不会向下找子类的
System.out.println(num);
}
}
package mypackage.day05.demo01;
public class Zi extends Fu {
int numZi = 20;
int num = 200;
public void printZi(){
// 因为本类当中有num,所以这里用的是本类的num
System.out.println(num);
}
public void method(){
int num = 300;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
package mypackage.day05.demo01;
/*
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量:
该方法属于谁,就优先用谁,没有则向上找。
*/
public class DemoFuZi {
public static void main(String[] args) {
Fu f = new Fu(); // 创建父类对象
System.out.println(f.numFu); // 只能使用父类的东西,没有任何子类内容
Zi z = new Zi();
System.out.println(z.numFu); // 10
System.out.println(z.numZi); // 20
// 等号左边是谁,就优先用谁
System.out.println(f.num);
System.out.println(z.num); // 优先子类
f.printFu();
// 这个方法是子类的,优先用子类的,没有再向上找
z.printZi();
// 这个方法是在父类当中定义的,
z.printFu();
System.out.println("==========================");
z.method();
}
}
3、方法的重载
package mypackage.day05.demo02;
public class OldPhone {
public void call(){
System.out.println("打电话!!!");
}
public void send(){
System.out.println("发短信!!!");
}
public void show(){
System.out.println("显示号码!!!");
}
}
package mypackage.day05.demo02;
public class NewPhone extends OldPhone {
public void show(){
super.show();
System.out.println("显示头像!!!");
System.out.println("显示日期!!!");
}
}
package mypackage.day05.demo02;
/*
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有则向上找。
注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。
重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。
重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。
方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。
*/
public class DemoOverride {
public static void main(String[] args) {
NewPhone nph = new NewPhone();
nph.call();
nph.send();
// 创建的是new了子类对象,所以优先用子类方法
nph.show();
}
}
4、super关键字的使用
package mypackage.day05.demo03;
public class Fu {
int num = 10;
public Fu(){
System.out.println("执行父类构造方法");
}
public void method(){
System.out.println("执行父类方法");
}
}
package mypackage.day05.demo03;
public class Zi extends Fu {
int num = 20;
public Zi(){
super();
System.out.println("执行子类构造方法");
}
@Override
public void method() {
super.method();
System.out.println(super.num);
}
}
package mypackage.day05.demo03;
public class DemoSuper {
public static void main(String[] args) {
Zi z = new Zi();
z.method();
}
}
5、this关键字的使用
package mypackage.day05.demo04;
public class Fu {
int num = 10;
public void method(){
System.out.println("执行父类方法");
}
public Fu(){
System.out.println("执行父类构造方法");
}
}
package mypackage.day05.demo04;
public class Zi extends Fu {
int num = 20;
public void methodA() {
System.out.println("执行方法A");
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
public void methodB() {
this.methodA();
System.out.println("执行方法B");
}
public Zi() {
this(3);
}
public Zi(int num) {
this(12,34);
System.out.println("执行1个参数的构造函数");
}
public Zi(int num1, int num2) {
super();
System.out.println("执行2个参数构造函数");
}
}
package mypackage.day05.demo04;
public class DemoThis {
public static void main(String[] args) {
Zi z = new Zi();
z.methodB();
}
}
6、抽象方法与抽象类
package mypackage.day05.demo05;
public abstract class Animal {
public abstract void eat();
public void method(){
System.out.println("正常方法");
}
}
package mypackage.day05.demo05;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!!!");
}
}
package mypackage.day05.demo05;
public class DemoAbstract {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
}
}
7、发红包案例
package mypackage.day05.demo06;
public class User {
private String Name;
private int socket;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getSocket() {
return socket;
}
public void setSocket(int socket) {
this.socket = socket;
}
public User(String name, int socket) {
Name = name;
this.socket = socket;
}
public User() {
}
public void show(){
System.out.println("我叫"+Name+",钱包里有"+socket);
}
}
package mypackage.day05.demo06;
import java.util.ArrayList;
public class Manage extends User{
public Manage(){
}
public Manage(String name, int socket) {
super(name, socket);
}
public ArrayList<Integer> send(int totalsend,int count){
ArrayList<Integer> redlist = new ArrayList<>();
if (totalsend>super.getSocket()){
System.out.println("余额不足");
return redlist;
}
int div = totalsend/count;
int mod = totalsend%count;
for (int i = 0; i < count-1; i++) {
redlist.add(div);
}
redlist.add(mod+div);
super.setSocket(super.getSocket()-totalsend);
return redlist;
}
}
package mypackage.day05.demo06;
import java.util.ArrayList;
import java.util.Random;
public class Receive extends User {
public Receive(){
}
public Receive(String name, int socket) {
super(name, socket);
}
public void recieve(ArrayList<Integer> list){
Random random = new Random();
int index = random.nextInt(list.size());
int getmoney = list.remove(index);
super.setSocket(super.getSocket()+getmoney);
}
}
package mypackage.day05.demo06;
import java.util.ArrayList;
public class DemoSendRedbag {
public static void main(String[] args) {
Manage jim = new Manage("Jim", 100);
Receive one = new Receive("one", 0);
Receive two = new Receive("two", 0);
Receive three = new Receive("three", 0);
jim.show();
one.show();
two.show();
three.show();
System.out.println("================================");
ArrayList<Integer> red = jim.send(20,3);
one.recieve(red);
two.recieve(red);
three.recieve(red);
jim.show();
one.show();
two.show();
three.show();
System.out.println("================================");
}
}