【继承、super、this、抽象类】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package cn.itcast.day09.demo01;

// 定义了员工的另一个子类:助教
public class Assistant extends Employee {
}

package cn.itcast.day09.demo01;

/*
在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。

定义父类的格式:(一个普通的类定义)
public class 父类名称 {
    // ...
}

定义子类的格式:
public class 子类名称 extends 父类名称 {
    // ...
}
 */
public class Demo01Extends {

    public static void main(String[] args) {
        // 创建了一个子类对象
        Teacher teacher = new Teacher();
        // Teacher类当中虽然什么都没写,但是会继承来自父类的method方法。
        teacher.method();

        // 创建另一个子类助教的对象
        Assistant assistant = new Assistant();
        assistant.method();
    }

}

package cn.itcast.day09.demo01;

// 定义一个父类:员工
public class Employee {

    public void method() {
        System.out.println("方法执行!");
    }

}

package cn.itcast.day09.demo01;

// 定义了一个员工的子类:讲师
public class Teacher extends Employee {

}

package cn.itcast.day09.demo02;

/*
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:

直接通过子类对象访问成员变量:
    等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量:
    该方法属于谁,就优先用谁,没有则向上找。
 */
public class Demo01ExtendsField {

    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); // 10
        System.out.println(zi.numZi); // 20
        System.out.println("===========");

        // 等号左边是谁,就优先用谁
        System.out.println(zi.num); // 优先子类,200
//        System.out.println(zi.abc); // 到处都没有,编译报错!
        System.out.println("===========");

        // 这个方法是子类的,优先用子类的,没有再向上找
        zi.methodZi(); // 200
        // 这个方法是在父类当中定义的,
        zi.methodFu(); // 100
    }

}

package cn.itcast.day09.demo02;

public class Fu {

    int numFu = 10;

    int num = 100;

    public void methodFu() {
        // 使用的是本类当中的,不会向下找子类的
        System.out.println(num);
    }

}

package cn.itcast.day09.demo02;

public class Zi extends Fu {

    int numZi = 20;

    int num = 200;

    public void methodZi() {
        // 因为本类当中有num,所以这里用的是本类的num
        System.out.println(num);
    }

}

package cn.itcast.day09.demo03;

/*
局部变量:         直接写成员变量名
本类的成员变量:    this.成员变量名
父类的成员变量:    super.成员变量名
 */
public class Demo01ExtendsField {

    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.method();
    }

}

package cn.itcast.day09.demo03;

public class Fu {

    int num = 10;

}

package cn.itcast.day09.demo03;

public class Zi extends Fu {

    int num = 20;

    public void method() {
        int num = 30;
        System.out.println(num); // 30,局部变量
        System.out.println(this.num); // 20,本类的成员变量
        System.out.println(super.num); // 10,父类的成员变量
    }

}

package cn.itcast.day09.demo04;

/*
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
    创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。
 */
public class Demo01ExtendsMethod {

    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.methodFu();
        zi.methodZi();

        // 创建的是new了子类对象,所以优先用子类方法
        zi.method();
    }

}

package cn.itcast.day09.demo04;

public class Fu {

    public void methodFu() {
        System.out.println("父类方法执行!");
    }

    public void method() {
        System.out.println("父类重名方法执行!");
    }

}

package cn.itcast.day09.demo04;

public class Zi extends Fu {

    public void methodZi() {
        System.out.println("子类方法执行!");
    }

    public void method() {
        System.out.println("子类重名方法执行!");
    }

}

package cn.itcast.day09.demo05;

/*
方法覆盖重写的注意事项:

1. 必须保证父子类之间方法的名称相同,参数列表也相同。
@Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

2. 子类方法的返回值必须【小于等于】父类方法的返回值范围。
小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
小扩展提示:public > protected > (default) > private
备注:(default)不是关键字default,而是什么都不写,留空。
 */
public class Demo01Override {

}

package cn.itcast.day09.demo05;

public class Fu {

    public String method() {
        return null;
    }

}

package cn.itcast.day09.demo05;

public class Zi extends Fu {

    @Override
    public String method() {
        return null;
    }

}

package cn.itcast.day09.demo07;

/*
继承关系中,父子类构造方法的访问特点:

1. 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造。
2. 子类构造可以通过super关键字来调用父类重载构造。
3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。
 */
public class Demo01Constructor {

    public static void main(String[] args) {
        Zi zi = new Zi();
    }

}

package cn.itcast.day09.demo07;

public class Fu {

    public Fu() {
        System.out.println("父类无参构造");
    }

    public Fu(int num) {
        System.out.println("父类有参构造!");
    }

}

package cn.itcast.day09.demo07;

public class Zi extends Fu {

    public Zi() {
        super(); // 在调用父类无参构造方法
//        super(20); // 在调用父类重载的构造方法
        System.out.println("子类构造方法!");
    }

    public void method() {
//        super(); // 错误写法!只有子类构造方法,才能调用父类构造方法。
    }

}

package cn.itcast.day09.demo08;

public class Fu {

    int num = 10;

    public void method() {
        System.out.println("父类方法");
    }

}

package cn.itcast.day09.demo08;

/*
super关键字的用法有三种:
1. 在子类的成员方法中,访问父类的成员变量。
2. 在子类的成员方法中,访问父类的成员方法。
3. 在子类的构造方法中,访问父类的构造方法。
 */
public class Zi extends Fu {

    int num = 20;

    public Zi() {
        super();
    }

    public void methodZi() {
        System.out.println(super.num); // 父类中的num
    }

    public void method() {
        super.method(); // 访问父类中的method
        System.out.println("子类方法");
    }

}

package cn.itcast.day09.demo09;

public class Fu {

    int num = 30;

}

package cn.itcast.day09.demo09;

/*
super关键字用来访问父类内容,而this关键字用来访问本类内容。用法也有三种:

1. 在本类的成员方法中,访问本类的成员变量。
2. 在本类的成员方法中,访问本类的另一个成员方法。
3. 在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法当中要注意:
A. this(...)调用也必须是构造方法的第一个语句,唯一一个。
B. super和this两种构造调用,不能同时使用。
 */
public class Zi extends Fu {

    int num = 20;

    public Zi() {
//        super(); // 这一行不再赠送
        this(123); // 本类的无参构造,调用本类的有参构造
//        this(1, 2); // 错误写法!
    }

    public Zi(int n) {
        this(1, 2);
    }

    public Zi(int n, int m) {
    }

    public void showNum() {
        int num = 10;
        System.out.println(num); // 局部变量
        System.out.println(this.num); // 本类中的成员变量
        System.out.println(super.num); // 父类中的成员变量
    }

    public void methodA() {
        System.out.println("AAA");
    }

    public void methodB() {
        this.methodA();
        System.out.println("BBB");
    }

}

package cn.itcast.day09.demo10;

public class Demo {

    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.show();
        zi.method();
    }

}

package cn.itcast.day09.demo10;

public class Fu {

    int num = 10;

    public void method() {
        System.out.println("父类方法");
    }

}

package cn.itcast.day09.demo10;

public class Zi extends Fu {

    int num = 20;

    @Override
    public void method() {
        super.method(); // 调用了父类方法
        System.out.println("子类方法");
    }

    public void show() {
        int num = 30;
        System.out.println(num); // 30
        System.out.println(this.num); // 20
        System.out.println(super.num); // 10
    }

}

package cn.itcast.day09.demo11;

/*
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

如何使用抽象类和抽象方法:
1. 不能直接创建new抽象类对象。
2. 必须用一个子类来继承抽象父类。
3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4. 创建子类对象进行使用。
 */
public abstract class Animal {

    // 这是一个抽象方法,代表吃东西,但是具体吃什么(大括号的内容)不确定。
    public abstract void eat();

    // 这是普通的成员方法
//    public void normalMethod() {
//
//    }

}

package cn.itcast.day09.demo11;

public class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

}

package cn.itcast.day09.demo11;

public class DemoMain {

    public static void main(String[] args) {
//        Animal animal = new Animal(); // 错误写法!不能直接创建抽象类对象

        Cat cat = new Cat();
        cat.eat();
    }

}

package cn.itcast.day09.demo12;

public class DemoMain {

    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.eat();
    }

}

package cn.itcast.day09.demo12;

public abstract class Fu {

    public Fu() {
        System.out.println("抽象父类构造方法执行!");
    }

    public abstract void eat();

}

package cn.itcast.day09.demo12;

/*
一个抽象类不一定含有抽象方法,
只要保证抽象方法所在的类是抽象类,即可。

这样没有抽象方法的抽象类,也不能直接创建对象,在一些特殊场景下有用途。
 */
public abstract class MyAbstract {
}

package cn.itcast.day09.demo12;

public class Zi extends Fu {

    public Zi() {
        // super();
        System.out.println("子类构造方法执行");
    }

    @Override
    public void eat() {
        System.out.println("吃饭饭");
    }
}

package cn.itcast.day09.demo13;

// 最高的抽象父类
public abstract class Animal {

    public abstract void eat();

    public abstract void sleep();

}

package cn.itcast.day09.demo13;

public class DemoMain {

    public static void main(String[] args) {
//        Animal animal = new Animal(); // 错误!

//        Dog dog = new Dog(); // 错误,这也是抽象类

        Dog2Ha ha = new Dog2Ha(); // 这是普通类,可以直接new对象。
        ha.eat();
        ha.sleep();
        System.out.println("==========");

        DogGolden golden = new DogGolden();
        golden.eat();
        golden.sleep();
    }


}

package cn.itcast.day09.demo13;

// 子类也是一个抽象类
public abstract class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    // public abstract void sleep();
}

package cn.itcast.day09.demo13;

public class Dog2Ha extends Dog {
    @Override
    public void sleep() {
        System.out.println("嘿嘿嘿……");
    }
}

package cn.itcast.day09.demo13;

public class DogGolden extends Dog {
    @Override
    public void sleep() {
        System.out.println("呼呼呼……");
    }
}

package cn.itcast.day09.demo14;

import java.util.ArrayList;

public class MainRedPacket {

    public static void main(String[] args) {
        Manager manager = new Manager("群主", 100);

        Member one = new Member("成员A", 0);
        Member two = new Member("成员B", 0);
        Member three = new Member("成员C", 0);

        manager.show(); // 100
        one.show(); // 0
        two.show(); // 0
        three.show(); // 0
        System.out.println("===============");

        // 群主总共发20块钱,分成3个红包
        ArrayList<Integer> redList = manager.send(20, 3);
        // 三个普通成员收红包
        one.receive(redList);
        two.receive(redList);
        three.receive(redList);

        manager.show(); // 100-20=80
        // 6、6、8,随机分给三个人
        one.show();
        two.show();
        three.show();
    }

}

package cn.itcast.day09.demo14;

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; // 返回空集合
        }

        // 扣钱,其实就是重新设置余额
        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;
    }
}

package cn.itcast.day09.demo14;

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());
        // 根据索引,从集合当中删除,并且得到被删除的红包,给我自己
        int delta = list.remove(index);
        // 当前成员自己本来有多少钱:
        int money = super.getMoney();
        // 加法,并且重新设置回去
        super.setMoney(money + delta);
    }
}

package cn.itcast.day09.demo14;

public class User {

    private String name; // 姓名
    private int money; // 余额,也就是当前用户拥有的钱数

    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;
    }
}

博主聊聊:今日份笔记,小可爱们,请签收!

最后老规矩与君共勉:

你可以放弃选择,但不要选择放弃!

这辈子没办法做太多事情,

所以每一件事情都要做到精彩绝伦!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值