java基础---多态、抽象类、object、解析以及小结

1 Object(掌握)

Object类是所有类型的父类

一个类如果没有父类,JVM在运行的时候会为这个类默认指定一个父类(Object)

注意:Java只能支持单继承,也就是说一个子类最多只能继承一个父类

public class  Person extends Object{
    
}

Object成员方法如下:

场景:我定义一个类Student,这个类默认会继承Object,此时我让Student去覆写Object的toString()方法,目的将Student转换为String类型

package com.sxt.day02.demo02;

import java.util.Objects;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 10:13
 * @Version 1.0
 **/
public class Student {
    private String name;

    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 将学生的属性信息转换成字符串,此时覆写了Object类型的toString()方法
     * @return 学生的字符串信息
     */
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

测试类:

package com.sxt.day02.demo02;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 10:17
 * @Version 1.0
 **/
public class TestStudent {

    public static void main(String[] args) {
        Student tom = new Student();
        tom.setAge(18);
        tom.setName("Tom");
        // tomInfo 存储量tom对象的信息
        /**
         * 实体类一定要覆写Object类型的toString方法,该方法能够像外界提供对象的信息,所以也叫作名片方法
         * */
        /**
         * 程序执行的时候jvm会检查tom对象有没有定义toString()方法,如果定义了就调用,如果没定义
         * 就调用父类型的toString()方法,此时Student的父类型是Object
         */
        String tomInfo = tom.toString();
        System.out.println(tomInfo);
    }
}

场景:我定义一个类Student,此时我让Student去覆写Object的equals()和hashCode()方法

package com.sxt.day02.demo02;

import java.util.Objects;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 10:13
 * @Version 1.0
 **/
public class Student {
    private String name;

    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 将学生的属性信息转换成字符串
     * @return
     */
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        // 参数的地址跟当前对象的地址一样就返回true
        // this此时表示tom1 , o此时表示tom2
        if (this == o) return true;
        // 参数为空或者类新信息不一致,返回false
        if (o == null || getClass() != o.getClass()) return false;
        // 此时逐个比较tom1和tom2的每个属性值,如果属性值全部相等返回true,否则返回false
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

测试类:

package com.sxt.day02.demo02;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 10:27
 * @Version 1.0
 **/
public class TestEquals {
    /**
     * 创建两个对象,调用equals判断真假
     * @param args
     */
    public static void main(String[] args) {
        Student tom1 = new Student();
        Student tom2 = new Student();
        tom1.setName("Tom");
        tom1.setAge(18);
        tom2.setName("Tom");
        tom2.setAge(18);
        // 没有覆写Object类型的equals()方法的情况下结果:false
        // 如何由false变为true?此时Student需要覆写Object类型的equals()和hashCode()
        System.out.println(tom1.equals(tom2));
    }
}

注意:工作中定义实体类(例如:Farmer、Student),必须覆写Object类型的toString()、hashCode()、equals()方法。

2 对象之间的关联(理解)

如果说继承是父子之间的垂直关系(父在上,子在下),那么关联就是水平关系(例如:学生有车)

继承:is a

关联:has a

共性:都能够做到代码的复用

场景:学生有车

package com.sxt.day02.demo03;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:03
 * @Version 1.0
 **/
public class Car {
    private String bread;

    private String color;

    public String getBread() {
        return bread;
    }

    public void setBread(String bread) {
        this.bread = bread;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Car(String bread, String color) {
        this.bread = bread;
        this.color = color;
    }

    /**
     * 车有启动的行为
     */
    public void start(){
        System.out.println(bread+"启动了,颜色"+color);
    }


    public void speed(){
        System.out.println(bread+"加速");
    }

    public void stop(){
        System.out.println(bread+"停止");
    }

    @Override
    public String toString() {
        return "Car{" +
                "bread='" + bread + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}

package com.sxt.day02.demo03;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:08
 * @Version 1.0
 **/
public class Student {
    /**
     * 学生有姓名
     */
    private String stuName;
    /**
     * 学生有车
     */
    private Car bmw = new Car("宝马","blue");

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Car getBmw() {
        return bmw;
    }

    public void setBmw(Car bmw) {
        this.bmw = bmw;
    }

    public Student() {
    }

    public Student(String stuName, Car bmw) {
        this.stuName = stuName;
        this.bmw = bmw;
    }

    public Student(String stuName) {
        this.stuName = stuName;
    }

    /**
     * 学生具备学习方法,先开车到学校,然后开始学习
     */
    public void study(){
        bmw.start();
        System.out.println(stuName+"开着车来学校学习");
    }
}
package com.sxt.day02.demo03;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:13
 * @Version 1.0
 **/
public class TestStudent {
    public static void main(String[] args) {
        /**
         * 1 创建学生对象
         * 2 调用study方法,让学生开着车来学习
         */
        Student tom = new Student("Tom");
        tom.study();
    }
}

关联的好处:代码复用,此时多个学生对象都可以使用Car的行为

3 深入向上转型(重点)

package com.sxt.day02.demo04;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:32
 * @Version 1.0
 * 所有形状的父类,每个形状都有绘画的方法
 **/
public class Shape {
    public void draw(){
        System.out.println("形状Shape开始绘画");
    }
}

package com.sxt.day02.demo04;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:32
 * @Version 1.0
 * 圆形是形状的子类:子类覆盖了父类的方法
 **/
public class Circle extends Shape {
    public void draw() {
        System.out.println("圆形Circle开始绘画");
    }
}
package com.sxt.day02.demo04;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:33
 * @Version 1.0
 矩形是形状的子类:子类覆盖了父类的方法
 **/
public class Rectangle extends Shape {
    public void draw(){
        System.out.println("矩形Rectangle开始绘画");
    }
}

package com.sxt.day02.demo04;

/**
 * @Description 三角形是形状的子类:子类覆盖了父类的方法
 * @Author caojie
 * @Date 2020/7/22 11:34
 * @Version 1.0
 **/
public class Triangle extends  Shape{
    public void draw(){
        System.out.println("三角形 开始绘画");
    }
}

package com.sxt.day02.demo04;

import com.sun.scenario.animation.shared.TimerReceiver;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:35
 * @Version 1.0
 * 在纸上面画形状
 **/
public class Paper {
    /**
     * 在纸上面操作圆形(画圆形)
     * @param circle
     */
    public static void operatorCircle(Circle circle){
        circle.draw();
    }
    /**
     * 在纸上面画三角形
     * @param triangle
     */
    public static void operatorTirangle(Triangle triangle){
        triangle.draw();
    }
    /**
     * 在纸上面画矩形
     * @param rectangle
     */
    public static void operatorRectangle(Rectangle rectangle){
        rectangle.draw();
    }
    /**
     * 创建三个子类对象,然后调用operator相关的方法进行绘画
     * @param args
     */
    public static void main(String[] args) {
        Circle cc = new Circle();
        Triangle tt = new Triangle();
        Rectangle rr = new Rectangle();
        // 调用静态方法进行绘画操作
        operatorCircle(cc);
        operatorRectangle(rr);
        operatorTirangle(tt);
    }
}

上面的示例有缺陷,每增加一个子类,我都要修改Perper类,都要添加具体的operatortXXX方法,代码无法复用

优化上一个示例,只定义一个operator(Shape sh)方法,将父类作为形参,程序运行的时子类作为实参传入到父类中。

package com.sxt.day02.demo04;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:35
 * @Version 1.0
 * 在纸上面画形状
 *
 **/
public class Paper2 {
    /**
     * 在纸上操作(画)形状
     * Paper只关注形状,不用关注具体的子类
     * 此时使用父类作为形参
     * @param sh
     */
    public static void operator(Shape sh){
        sh.draw();
    }
    /**
     * 创建三个子类对象,然后调用operator相关的方法进行绘画
     * @param args
     */
    public static void main(String[] args) {
        Circle cc = new Circle();
        Triangle tt = new Triangle();
        Rectangle rr = new Rectangle();
        // 调用静态方法进行绘画操作
        //操作圆形
        operator(cc);
        //操作 三角形
        operator(tt);
        // 操作矩形
        operator(rr);
    }
}

参数向上转型小结:父类作为形参,子类作为实参,程序运行期实参传入到形参中

// sh此时有两种状态,编译期sh指向父类型Shape,运行期sh指向子类型
public static void operator(Shape sh)
    

4 多态(重点)

概念1:编译期不知道子类对象的类型,而是在运行期创建对象,调用恰当的方法

概念2:父类定义共性的行为,例如:Shape作为父类定义draw(), 如何绘画让子类去实现,同一个方法,可以由每个子类进行不同的实现(圆形、三角形、矩形它们的绘画方式不一样,但是他们都具备绘画的行为)

多态的支撑点:方法覆写和向上转型

目的:父类定义共性行为(做什么),通常父类不去做事,如何做全部下沉到子类。

做什么(父类定义的void draw()方法)和怎么做(子类来覆盖父类的void draw())分离

场景:形状体系,一个父类,三个子类。输入1画圆形,输入2画三角形,输入3画矩形

特点:编译期不知道创建那个子类,只有在运行期根据客户输入的数字才能创建具体的对象

package com.sxt.day02.demo05;

/**
 * @Description 所有形状类型的父类
 * @Author caojie
 * @Date 2020/7/22 14:21
 * @Version 1.0
 **/
public class Shape {
    /**
     * 父类定义做什么
     * 此时方法体为空,也是一个哑巴方法
     * 怎么做下沉到子类
     */
    public void draw(){}
}

package com.sxt.day02.demo05;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:32
 * @Version 1.0
 * 圆形是形状的子类:子类覆盖了父类的方法
 **/
public class Circle extends Shape {
    public void draw() {
        System.out.println("形状Circle开始绘画");
    }
}
package com.sxt.day02.demo05;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:33
 * @Version 1.0
 **/
public class Rectangle extends Shape {
    public void draw(){
        System.out.println("形状矩形Rectangle开始绘画");
    }
}

package com.sxt.day02.demo05;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 11:34
 * @Version 1.0
 **/
public class Triangle extends Shape {
    public void draw(){
        System.out.println("三角形 开始绘画");
    }
}

package com.sxt.day02.demo05;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 14:23
 * @Version 1.0
 * 形状工厂,唯一职责就是创建形状相关的产品
 **/
public class ShapeFactory {

    /**
     * 根据客户输入的参数来决定创建的产品
     * 输入1画圆形,输入2画三角形,输入3画矩形
     * 注意:sh 此时有两种状态,编译期sh是Shape类型,运行期一旦该方法被调用sh就是子类型
     * @param index
     * @return 形状
     */
    public static Shape create(int index){
        Shape sh = null;
        switch (index) {
            case 1:
                sh = new Circle();
                break;
            case 2:
                sh = new Triangle();
                break;
            case 3:
                sh = new Rectangle();
                break;
        }
        return sh;
    }
}

package com.sxt.day02.demo05;

import java.util.Scanner;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 14:26
 * @Version 1.0
 * 在纸上绘画形状
 * 1 定义Scanner
 * 2 接收用户的输入
 * 3 根据用户输入的数字使用工厂的静态方法来创建具体的对象
 * 4 调用对象的draw()方法进行绘画
 * 多态好处:外界只用关注父类(Shape),可以完全忽略子类的存在
 **/
public class Paper {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入数字:输入1画圆形,输入2画三角形,输入3画矩形");
        int num = input.nextInt();
        // check
        if(num<1 || num>3){
            System.err.println("输入错误程序退出:输入1画圆形,输入2画三角形,输入3画矩形");
            return;
        }
        //使用工厂创建对象
        Shape sh = ShapeFactory.create(num);
        //调用对象的draw()行为
        sh.draw();
    }
}

5 抽象(重点)

抽象是建立在多态的基础上的,将所有事物像的行为抽取出来,定义在父类中。例如:Shape类有一个draw()方法

抽象的特征:1 是一个很泛的概念,无法实例化对象(无法创建对象)

​ 2 父类不能new对象,只能将共有的行为抽取到父类中

抽象的关键字:abstract,该关键字可以修饰类、修饰方法。一旦某个类被abstract修饰那么该类叫做抽象类,抽象类通常作为父类,让子类去继承。如果一个子类继承了抽象类那么必须覆盖抽象类中的所有抽象方法。

抽象类中可以定义抽象方法、也可以定义非抽象方法、还可以定义静态属性和非静态属性

抽象类不能使用new关键字创建对象。

1)初识抽象类

注意:如果一个抽象类中没有抽象方法那么将失去意义,因为抽象类通常作为父类,子类去继承抽象类覆写抽象方法。

2)形状的示例

场景:定义一个抽象类Shape作为父类,每个形状都有绘画的行为和清除(clear())的行为, 他们是一个整体,每个形状必须先绘画然后清除

package com.sxt.day02.demo06;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:11
 * @Version 1.0
 *
 **/
public abstract class Shape {
    /**
     * 抽象类不仅仅能够定义抽象方法,还能够定义具体方法,一旦抽象类中定义了具体方法,
     * 那么子类可以无条件的使用,前提是具体方法不能私有
     * 
     */
    public void action(){
        draw();
        clear();
    }
    /***
     *
     * 一旦某个方法使用abstract修饰,该方法就是一个抽象方法,抽象方法不能有方法体
     * 编译错误:抽象方法不能有方法体
     * Abstract methods cannot have a body
     */
//    public abstract void draw(){}
    public abstract void draw();

    public abstract void clear();
}

小结:抽象类中具体方法可以调用抽象方法,上面代码编译期draw()和clear()是父类的方法,运行期由于在工厂中创建了具体类型的对象,所以运行期draw()和clear()调用的是子类的方法。

​ 子类可以覆盖父类的抽象方法,也可以使用父类具体方法,工作中尽量不要覆盖父类的具体方法,只覆盖父类的抽象方法。

​ 工作中如果使用抽象类,抽象类通常作为父类

​ 子类继承父类最后继承抽象类,尽量不要继承具体类

package com.sxt.day02.demo06;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:18
 * @Version 1.0
 **/
// 编译错误:子类继承抽象类,必须覆写抽象类中的抽象方法
// Class 'Circle' must either be declared abstract or implement abstract method 'draw()' in 'Shape
// class Circle extends  Shape{
// }
class Circle extends Shape{

    /**
     * @Override 跟功能无关:告诉我此时子类的draw()方法是覆盖了父类的draw()方法
     */
    @Override
    public void draw() {
        System.out.println("圆形绘画");
    }

    @Override
    public void clear() {
        System.out.println("圆形清理");
    }
}

package com.sxt.day02.demo06;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:30
 * @Version 1.0
 **/
 class Rectangle extends Shape{
    @Override
    public void draw() {
        System.out.println("矩形绘画");
    }

    @Override
    public void clear() {
        System.out.println("矩形清理");
    }
}
package com.sxt.day02.demo06;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:30
 * @Version 1.0
 **/
class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("三角形绘画");
    }

    @Override
    public void clear() {
        System.out.println("三角形清理");
    }
}

package com.sxt.day02.demo06;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:33
 * @Version 1.0
 **/
public class ShapeFactory {
    public static Shape createShape(int index) {
        Shape sh  = null;
        switch (index) {
            case 1:
                sh = new Circle();
                break;
            case 2:
                sh = new Triangle();
                break;
            case 3:
                sh = new Rectangle();
                break;
        }
        return sh;
    }
}

测试类:

package com.sxt.day02.demo07;

import com.sxt.day02.demo06.Shape;
import com.sxt.day02.demo06.ShapeFactory;

import java.util.Scanner;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 15:35
 * @Version 1.0
 **/
public class Paper {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入数字:输入1画圆形,输入2画三角形,输入3画矩形");
        int num = input.nextInt();
        // check
        if(num<1 || num>3){
            System.err.println("输入错误程序退出:输入1画圆形,输入2画三角形,输入3画矩形");
            return;
        }
        // 根据输入的整数创建形状
        Shape sh = ShapeFactory.createShape(num);
        sh.action();
    }
}

6 接口

接口是一个标准,或者说接口是一个协议,如果某个类实现了接口就必须准许接口的标准(协议)

JDK1.8以前接口只能定义常量,定义方法声明,不能定义方法的实现,方法实现必须由子类去覆写

JDK1.8之后,提供了一个default关键字,可以在接口中定义方法的实现

一个类最多只能继承(extends)一个父类

一个类可以实现(implements)N个接口

接口中定义的属性必须赋初始值,也就意味着接口中的属性都是 public static final

JDK1.8之前接口中定义的方法,默认是public abstract

小结:接口使用interface关键字定义,如果子类实现接口必须使用implements

​ 一个子类可以实现多个接口,可以变相的多重继承

接口是一个标准,如果某个类实现接口必须覆盖接口中定义的所有方法,除了default以外

接口和实现类之间的关系?

肯德基和肯德基加盟店之间的关系,加盟店必须实现KFC所有的标准

package com.sxt.day02.demo08;

public interface Shape {
    // int num =10;
    // 程序运行的时候默认会为你添加 public static final
    public static final double CIRCLE_PI = 3.14;

    public  void draw();

    // 接口中没有定义public,jvm运行的时候自动帮你加上  public abstract
    // public abstract void clear();
    void clear();
    // 接口不能定义private和protected
    // protected void aac();
}

场景1:定义一个形状接口Shape,改接口只有一个方法draw(), 圆形去实现Shape接口

package com.sxt.day02.demo09;

/**
 * 形状是一个接口,也是一个标准,所有实现Shape的子类必须实现接口中所有的方法
 */
public interface Shape {
    void draw();
}

package com.sxt.day02.demo09;

import java.sql.SQLOutput;

/**
 * @Description Circle 实现Shape接口,必须覆写接口中所有的方法(除了default不用覆写)
 * @Author caojie
 * @Date 2020/7/22 16:27
 * @Version 1.0
 **/
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("圆形正在绘画...............");
    }
}

package com.sxt.day02.demo09;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:28
 * @Version 1.0
 **/
public class Test {
    public static void main(String[] args) {
        Shape sh = new Circle();
        sh.draw();
    }
}

场景2:定义一个形状接口Shape, 有clear()和draw()方法,定义三个形状分别是圆形、矩形、三角形去实现接口,一次创建10个形状,具体的形状使用随机数产生,1圆形2三角形3矩形

从这里开始看 !!!!!
package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:33
 * @Version 1.0
 **/
public interface Shape {
    void draw();
    void clear();

    /**
     * default 修饰的方法是默认实现的方法,子类可以不用实现默认方法
     * 实现类可以使用default修饰的方法
     */
    public default void action(){
        draw();
        clear();
    }
}

package com.sxt.day02.demo10;

import java.sql.SQLOutput;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:36
 * @Version 1.0
 **/
public class Circle implements  Shape {
    @Override
    public void draw() {
        System.out.println("圆形绘画");
    }

    @Override
    public void clear() {
        System.out.println("圆形清除");
    }
}

package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:36
 * @Version 1.0
 **/
public class Rectangle implements Shape{
    @Override
    public void draw() {
        System.out.println("矩形绘画");
    }

    @Override
    public void clear() {
        System.out.println("矩形清除");
    }
}

package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:37
 * @Version 1.0
 **/
public class Triangle implements Shape{
    @Override
    public void draw() {
        System.out.println("三角形绘画");
    }

    @Override
    public void clear() {
        System.out.println("三角形清除");
    }
}

package com.sxt.day02.demo11;

import com.sxt.day02.demo10.Circle;
import com.sxt.day02.demo10.Rectangle;
import com.sxt.day02.demo10.Shape;
import com.sxt.day02.demo10.Triangle;

import java.util.Random;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:41
 * @Version 1.0
 * 1定义形状数组
 * 2 创建随机数对象
 * 3 通过数字产生形状 1圆形2三角形3矩形
 * 4 调用形状的方法
 **/
public class Paper {
    /*
    运行期存储具体的形状
     */
    private static  Shape [] shapes = new Shape[10];
    // 填充数组的元素
    static{
        Random random = new Random();
        for (int i = 0; i < shapes.length ; i++) {
            //产生随机数
            int num = random.nextInt(3)+1;
            switch (num){
                case 1:
                    shapes[i] = new Circle();
                    break;
                case 2:
                    shapes[i] = new Triangle();
                    break;
                case 3:
                    shapes[i] = new Rectangle();
                    break;
            }
        }
    }

    public static void main(String[] args) {
            // 便利数组的每个元素,调用action()方法
        for(Shape sh : shapes){
            sh.action();
            System.out.println("---------------------------------------");
        }
    }
}

场景:如果创建的对象是圆形(Circle)除了执行draw()方法和clear()方法之外还要计算面积

如何做?

需要判断Shape对象是否是圆形,如果是将其向下转换为Circle,然后调用Circle的draw()方法

package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:33
 * @Version 1.0
 **/
public interface Shape {
    void draw();
    void clear();

    /**
     * default 修饰的方法是默认实现的方法,子类可以不用实现默认方法
     * 实现类可以使用default修饰的方法
     */
//    public default void action(){
//        draw();	
//        clear();
//    }
}

package com.sxt.day02.demo10;

import java.sql.SQLOutput;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:36
 * @Version 1.0
 * 注意:工作中向外界只暴露接口,实现类最好向外界隐藏(不适用public修饰,外界无法new)
 **/
public class Circle implements  Shape {
    @Override
    public void draw() {
        System.out.println("圆形绘画");
    }

    @Override
    public void clear() {
        System.out.println("圆形清除");
    }

    /**
     * 计算面积的方法是圆形独有的,其他子类没有这个方法
     * @param radius 半径
     * @return 面积
     */
    public double calcArea(int radius){
        return radius * radius * 3.14;
    }
}

package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:36
 * @Version 1.0
 **/
public class Rectangle implements Shape{
    @Override
    public void draw() {
        System.out.println("矩形绘画");
    }

    @Override
    public void clear() {
        System.out.println("矩形清除");
    }
}

package com.sxt.day02.demo10;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:37
 * @Version 1.0
 **/

public class Triangle implements Shape{
    @Override
    public void draw() {
        System.out.println("三角形绘画");
    }

    @Override
    public void clear() {
        System.out.println("三角形清除");
    }
}

测试类:

package com.sxt.day02.demo11;

import com.sxt.day02.demo10.Circle;
import com.sxt.day02.demo10.Rectangle;
import com.sxt.day02.demo10.Shape;
import com.sxt.day02.demo10.Triangle;

import java.util.Random;

/**
 * @Description TODO
 * @Author caojie
 * @Date 2020/7/22 16:41
 * @Version 1.0
 * 1定义形状数组
 * 2 创建随机数对象
 * 3 通过数字产生形状 1圆形2三角形3矩形
 * 4 调用形状的方法
 **/
public class Paper {
    /*
    运行期存储具体的形状
     */
    private static  Shape [] shapes = new Shape[10];
    // 填充数组的元素
    static{
        Random random = new Random();
        for (int i = 0; i < shapes.length ; i++) {
            //产生随机数
            int num = random.nextInt(3)+1;
            switch (num){
                case 1:
                    shapes[i] = new Circle();
                    break;
                case 2:
                    shapes[i] = new Triangle();
                    break;
                case 3:
                    shapes[i] = new Rectangle();
                    break;
            }
        }
    }

    public static void main(String[] args) {
            // 便利数组的每个元素,调用action()方法
        for(Shape sh : shapes){
           // sh.action();
            sh.draw();
            // sh编译期是Shape类型,将强制转换为Circle,强制转换也叫作向下转型
            // 向下转型不安全,因为sh编译期是Shape,形状不一定是圆形
            // 通常在工作中向下转型之前要做check,判断当前的sh是否是圆形的实例
            // 条件成立:表示sh是圆形的实例,执行向下转型
            if(sh instanceof Circle){
                Circle circle = (Circle)sh;
                double area = circle.calcArea(3);
                System.out.println("圆形面积="+area);
                sh.clear();
            }
            sh.clear();
            System.out.println("---------------------------------------");
        }
    }
}

7 小结

1 Object类型 所有类型的父类

​ toString() equals()

2 对象之间的关联

​ 平行关系: has a 学生有车

3 向上转型

​ 编译期父类作为形参,运行期子类可以向上转换为父类

​ 编译期就已经知道对象的类型

4 多态

​ 运行期根据客户传递的参数创建对象,调用恰当的方法

​ Shape sh;

​ sh 编译期是父类 运行期根据工厂创建的形状就是一个子类型

5 抽象

​ 抽出向的行为

​ 父类定义做什么,怎么做下沉到子类。目的:做什么和怎么做分离

​ 通常父类定义共性的行为,父类最好不定义属性,所有的属性下沉到子类,因为 圆形和三角形他们的属性不同。

6 接口

​ 接口和抽象类的共性:都是用于父子之间的继承

​ 子类通常使用extends关键字继承父类,使用implements实现接口

​ 一个子类可以实现多个接口

预习:抽象类和接口区别

​ 接口多继承

​ 内部类

​ 垃圾回收

你可能感兴趣的:(java,多态,抽象类,object,接口)