Java学习记录(十二)—— 类_继承_多态_抽象类_接口

多态

// 打印形状
class Shape{
    public void draw(){
    }
}
// 打印矩形
class Rect extends Shape{
    @Override
    public void draw(){
        System.out.println("♦");
    }
}
// 打印圆圈
class Circle extends Shape{
    @Override
    public void draw(){
        System.out.println("⭕");
    }
}
class Flower extends Shape{
    @Override
    public void draw(){
        System.out.println("❀");
    }
}
public class Demo {
    public static void drawMap(Shape shape){
        shape.draw();
    }
    public static void main(String[] args) {
        Rect rect = new Rect();
        drawMap(rect);

        Circle circle = new Circle();
        drawMap(circle);

        Flower flower = new Flower();
        drawMap(flower);
    }
}

多态中主要的问题就是向上转型运行时绑定两个关键点:

  • 向上转型:格式为:父类名称 对象名 = new 子类名称()
         含义为:右侧创建一个子类对象,把它当作父类来看待使用(把子类对象赋值给父类引用)

  • 运行时绑定:使用了向上转型新建了一个对象,由于子类对父类的一个方法进行了重写,如果使用新建的这个对象调用此方法,则在编译时该方法会调用父类方法,但运行时回绑定子类方法(通俗理解为:访问成员方法的规则是,new的是谁,优先使用谁,没有该方法再想上找、编译看左,运行看右

多态的优点:

  • 1、类调用者对类的使用成本进一步降低
  • 2、能够降低代码的“圈复杂度”,避免使用大量的 if-else
  • 3、可扩展能力更强

抽象类

  • 抽象类:包含抽象方法的类
  • 1、抽象类不能进行实例化
  • 2、抽象类当中,可以拥有与普通类一样的数据成员和方法
  • 3、抽象类可以被继承,可以方法向上转型
  • 4、当一个普通类继承了一个抽象类,则当前这个普通类必须要重写抽象类
  • 5、当普通类A继承了抽象类且不想不重写抽象类的方法,则将该普通类也变为abstract,即为抽象类A,就不需要进行实现了
  • 6、如果这个普通类B,继承了抽象类A,此时就要实现抽象方法(出来混,迟早要还)
  • 7、抽象方法不能是私有的(因为私有的不能被重写,抽象方法一定是会被重写的
  • 8、抽象类的出现,最大意义就是为了被继承
abstract class Shape{
    public abstract void drwa(); // 如果该方法被abstract修饰了,只能通过重写实现
    // 2、抽象类当中可以拥有与普通类一样的数据成员和方法
    public int age;
    public void func(){}
}
// 3、抽象类可以被继承
class Rect extends Shape{
    @Override
    public void draw(){
        System.out.println("♦")
    }
}
public class TestDemo{
    public static void drawMap(Shape shape){
        shape.draw(); // 可以通过shape引用调用抽象方法里的draw
    }
    public static void main(String[] args){
        // 1、抽象方法不能进行实例化,下面一行代码不正确
        // Shape shape = new Shape(); ×
        
        // 抽象类也可以发生向上转型
        drawMap(new Rect());
    }
}

接口

  • 接口:使用关键字 interface修饰
  • 1、接口当中的方法不能有具体的的实现,接口当中的方法,默认是:public abstract
  • 2、接口当中的成员变量,默认是public static final
  • 3、JDK1.8引入的新特性。使用default修饰的方法,默认方法,可以有具体实现
  • 4、接口不可以进行实例化:IShape ishape = new IShape();
  • 5、类和接口之间的关系是implements
```java
interface IShape{
    void draw();
}
class Rect implements IShape{
    @Override
    public void draw(){
        System.out.println("⚪")
    }
}
public class TestDemo{
    // 接口也可以向上转型
    public static void drawMap(IShape shape){ //动态绑定
        shape.draw();
    }
    public static void main(String[] args){
        drawMap(new Rect); //向上转型
    }
}
  • 6、一个类可以实现多个接口
  • 7、一个类可以继承类且同时实现多个接口class Test extends TestAabstract implements A,B,C{
  • 8、接口可以扩展多个接口
  • 所以接口的出现,就是为了解决java多继承的问题
interface A{
    void funcA();
}
interface B{
    void func();
}
interface C{
    void funcC();
}
// 接口之间的关系(不叫继承叫扩展)
interface D extends A{
    void funcD();
}
class F implements D{
    // 此处F重写了D中的两个方法,可以看到,D确实得到的扩展
    @Override
    public void funcA() {
    }
    @Override
    public void funcD() {
    }
} 
// 不一定必须是抽象类,普通类也可以,但只能继承一个类
abstract class TestAabstract{
    public abstract void funcAabstract();
}
class Test extends TestAabstract implements A,B,C{
    @Override
    public void funcA() {
    }
    @Override
    public void func() {
    }
    @Override
    public void funcC() {
    }
    @Override
    public void funcAabstract() {
    }
}
举例来实现多个接口

// 在写代码时,应当一个类(接口)就是一个java文件

class Animal{
    protected String name;
    // 带有一个参数的构造方法
    public Animal(String name){
        this.name = name;
    }
}
// 提供一组接口
interface IFlying{
    void fly();
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
// 写一个子类猫,猫会跑
class Cat extends Animal implements IRunning{
    // 父类有构造方法,此时子类必须先创建一个构造方法
    public Cat(String name){
        super(name);
    }
    @Override 
    public void run(){
        System.out.prinrln(this.name + "正在跑!")
    }
}

public class TestDemo{
    public static void main(String[] args){
        
    }
}

常见的三个接口

1、Comparable
class Student{
    public String name;
    public int score;
    //构造方法
    public Student(String name, int score){
        this.name = name;
        this.score = score;
    }
    // 重写toString方法
    @Override
    public String toString(){
        return "Student{" +
               "name = " + name + '\' +
               ", score =" + score + '}';
     }
}

public class TestDemo{
    public static void main(String[] args){
        Student[] students = new Student[3]; //定义一个数组
        // 把值扔进去
        students[0] = new Student("bit", 81);
        students[1] = new Student("bit", 63);
        students[2] = new Student("bit", 79);
        System.out.println(Arrays.toString(students));
        // 想要对数组进行排序
        Arrays.sort(students);
        System.out.println(Arrays.toString(students)); // 此时会报错
    }
}

这里放遇到的错误
错误中我们可以看到,此处是将每个数组都强制转换成了Comparable,每一个学生student都是一个对象,这里不知道对啥进行比较,所以会报错,我们可以实现一个接口,这个接口叫做Comparable

class Student implements Comparable<Student>{ //<>中填的是想要比较的类型
    public String name;
    public int score;
    //构造方法
    public Student(String name, int score){
        this.name = name;
        this.score = score;
    }
    // 重写toString方法
    @Override
    public String toString(){
        return "Student{" +
               "name = " + name + '\' +
               ", score =" + score + '}';
     }
     // 重写Comparable中的campareTo方法
     public int compareTo(Student o){ // 这个方法在此出的意思就是 学生与学生之间进行比较
         if(this.score > o.score){
             return 1;
         }else if(this.score == o.score){
             return 0;
         }else{
             return -1;
         }
     }
}
  • 对于Comparable接口来说,一般是用在类的内部的
2、比较器(Comparator)
class Student2{
    public String name;
    public int score;
    //构造方法
    public Student2(String name, int score){
        this.name = name;
        this.score = score;
    }
    // 重写toString方法
    @Override
    public String toString(){
        return "Student{" +
               "name = " + name + '\' +
               ", score =" + score + '}';
     }
}
// 单独写一个类,是根据分数的比较器
public class ScoreComparator implements Comparator<Student2>{
    // 实现重写该接口中的compare方法
    public int compare(Student2 o1, Student o2){
//        if(o1.score > o2.score){ // 以他们的分数作为比较
//            return 1;
//        }else if(o1.score == o2.score){
//            return 0;
//        }else{
//            return -1;
//        }
        // 可以直接写成
        return o1.score - o2.score;
    }    
}
// 根据姓名进行排序
public class ScoreComparator implements Comparator<Student2>{
    // 实现重写该接口中的compare方法
    public int compare(Student2 o1, Student o2){
        // 对String类型比较大小,使用.compareTo()方法
        return o1.name.compareTo(o2.name);
    }    
}

public TestDemo{
    public static void main(String[] args){
        student2[] students = new Student2[3];
        students[0] = new Student2("bit", 81);
        students[1] = new Student2("bit", 63);
        students[2] = new Student2("bit", 79);
        System.out.println(Arrays.toString(students));
        // 想要对数组进行排序
        // 根据分数进行排序
        ScoreComparator scoreComparator = new ScoreComparator();
        Array.sort(students, scoreComparator);
        // 在sort的源码中,有两个参数,第一个是数组名,第二个就是comparator,即以什么样的方式进行比较。
    }
}
3、
  • 1、如何拷贝对象
class Person implements Clonable{
    public String name;
    public Person(String name){
        this.name = name;
    }
    @Override
    public String toString(){
        return "PersonP" + 
               "name = " + name + '\' +
               '}'; 
    }
    // alt+ins -> Override Methods -> clone()
    @Override
    protected Object clone() throws CloneNotSupportedExeception{
        return super.clone();
    }
}
public class TestDemo03{
    public static void main(String[] args throws CloneNotSupportedExeception){
    // 涉及异常相关知识暂不做了解
        Person person1 =new Person("bit");
        Person person2 = (Person)persion1.clone(); //因为clone方法本身是Object类型为超级父类,所以要向下转型为Person
    }
}

  • 接口什么内容都没有,此时这个接口叫做:空接口,标记接口。此处的Clonable接口的作用是标记当前这个类是可以被克隆的
  • 克隆回拷贝一份副本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值