抽象类与接口

一、抽象类

1.1.抽象类的概述:

​ 我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。

  • 抽象类的特点:
  • 抽象类和抽象方法必须用abstract关键字修饰
  • 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类 (即带有抽象方法的)
  • 抽象类不能实例化
    因为它不是具体的。
    抽象类有构造方法,但是不能实例化,构造方法的作用是 用于子类访问父类数据的初始化
  • 抽象的子类
    a:被抽象类abstract修饰的子类,也是一个抽象类
    b:不加abstract的话,通过多态,抽象类的子类可以被实例化,但是必须重写抽象类中所有的抽象方法.
    抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
    Animal a = new Cat();(前提是cat已经被实例化)

1.2.抽象类的成员特点

  • 成员变量:抽象类的成员方法既可以是常量,也可以是变量,但是不可以抽象化
  • 构造方法:抽象类有成员方法,用于子类访问父类数据的初始化
  • 成员方法:既可以是抽象的也可以是非抽象的
    抽象类成员方法的特性:
    1.抽象方法:强制要求子类必须做的事,即子类必须重写父类有的抽象方法
    2.非抽象方法:子类可以从父类继承的,提高代码复用性

示例代码:

//这是一个抽象类
abstract class Animel{
    public abstract void eat();//正确,不带主体的抽象方法
    //public abstract void sleep() {}//报错,因为抽象方法不能有主体。即大括号中的代码块
    public void sleep(){
        System.out.println("睡觉");//这是抽象类中的一个非抽象方法,可以被子类继承的
    }
}
abstract class dog extends Animel{}//如果加了abstract,抽象类的子类也是抽象类

class cat extends Animel{
    public void eat() {
        System.out.println("吃饭");
        //不加abstract的话,通过多态,抽象类的子类可以被实例化,但是必须重写抽象类中所有的的方法
        //如果没有全部重写,将会报错
    }
}

public class AbstractTest {

    public static void main(String[] args) {

        //Animel a = new Animel();//错误,抽象类不能直接实例化
        Animel a= new cat();//抽象类通过多态实现子类实例化
        a.eat();
        a.sleep();//未被抽象的方法
        cat c= new cat();//具体对象调用
        c.eat();
        c.sleep();
    }

运行结果:

吃饭
睡觉
吃饭
睡觉

1.3.抽象类的注意事项

抽象类的使用限制

  1. 不能与final (冲突)
  2. private(冲突)
  3. static(无意义) 共存
    原因:首先因为被final和private修饰的方法不允许被重写或者覆盖,而被abstract修饰的方法又必须在子类中重写,所以这abstract与这两个关键字冲突,关于static关键字,因为被abstract修饰的方法不允许有方法体,而被static修饰的方法可以直接通过类名调用,而调用一个没有方法体的方法是没有意义的

1.4.抽象类总结

1、抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
2、抽象方法必须由子类来进行重写。
3、只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。
4、抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
5、子类中的抽象方法不能与父类的抽象方法同名。
6、abstract不能与final并列修饰同一个类。
7、abstract 不能与private、static、final或native并列修饰同一个方法。、

1.5.抽象类的三种调用方式

abstract class Animel{
    private int age ;
    private String name;
    abstract void eat() ;
    Animel(){};
    public Animel(String name,int age) {
        this.name=name;
        this.age=age;
    }
    public void SetName(String name) {
        this.name =name;
    }
    public void SetAge(int age) {
        this.age=age;
    }
    public String GetName() {
        return name;
    }
    public int GetAge() {
        return age;
    }
}
class dog extends Animel{
    public dog() {};
    public dog(String name,int age) {
        super(name,age);
    }
    public void eat() {
        System.out.println("狗吃肉");
    }

}
public class CatDemo {
    public static void main(String[] args) {
        //调用方式一,构造方法调用
        dog d = new dog("哈士奇",20);
        d.eat();
        System.out.println(d.GetAge()+"------"+d.GetName());
        System.out.println("------------");
        //   调用方式二,具体调用
        dog d1= new dog();
        d1.eat();
        d1.SetAge(19);
        d1.SetName("哈巴狗");
        System.out.println(d1.GetAge()+"------"+d1.GetName());
        System.out.println("------------");
        //调用方式三.抽象调用
        Animel d2 = new dog();
        d2.eat();
        d2.SetAge(99);
        d2.SetName("萌犬");
        System.out.println(d2.GetAge()+"------"+d2.GetName());
    }
}

二、接口

2.1.接口的概述

  • 接口用关键字interface表示 (注意,接口不需要加class)
    interface 接口名 {}

  • 类实现接口用implements
    class 类名 implements 接口名 {}

  • 接口不能直接实例化 ,如果需要实例化,必须按照多态的方式来实例化,即利用一个非抽象化的子类进行实例化

  • 接口的子类 ,可以是抽象类。但是意义不大。也可以是具体类。但是必须要重写接口中的所有抽象方法。

  • 接口并不是实际的一个类,而是功能的拓展,由此可见多态有三种实现方法:

    ​ A:具体类多态(很少用)
    ​ B:抽象类多态(常用)
    ​ C:接口多态(最常用)

    ps(1.接口名+Impl这种格式是接口的实现类惯用格式 ,2,在实现接口的时候需要注意调用的时候只能调用该接口有的方法 )

2.2.接口的成员特点

  • 成员变量:接口中的变量默认是常量,默认带有 public static final ,不可被重新赋值,同时因为它是静态的, 因此即使另一个类处于不同包下,也可以通过接口名.成员变量名来访问接口里的成员变量。,但是建议自己手动给出public static final,
  • 成员方法:接口中的方法只能是抽象方法,且默认为抽象方法,即使没有加抽象修饰符abstract,
    因为接口中的成员方法默认加了public abstract,但是为了直观,依旧建议自己手动给出public abstract ,而且, 接口中的成员方法与抽象类类似,都不带有方法主体
  • 构造方法:接口没有构造方法

2.3.接口与类之间的关系

  • 与类:
    继承关系,只能单继承,可以多层继承。(不允许存在son extends father, mother{}这种情况 )
  • 类与接口:
    实现关系,可以单实现,也可以多实现。(例如:class Son implements Father,Mother{})
    并且还可以在继承一个类的同时实现多个接口。(class son extends father implements mother,sister {}(解释:子类继承父类并实现母和姐妹接口))
  • 接口与接口:
    继承关系,可以单继承,也可以多继承。(interface Sister extends Father,Mother { })继承的接口,可以继承功能

三、抽象类与接口的区别

3.1.成员区别

  • ​ 抽象类:
    ​ 成员变量:可以变量,也可以常量
    ​ 构造方法:有 构造方法
    ​ 成员方法:可以抽象,也可以非抽象
  • 接口:
    成员变量:只可以常量 (即被static final)
    成员方法:只有抽象 方法
    没有构造方法

3.2.关系区别

  • 类与类 继承,单继承
  • 类与接口 实现,单实现,多实现
  • 接口与接口 继承,单继承,多继承

3.3.设计理念区别

​ 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能,大致来说当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口,通俗的说,类用来抽象共性,而接口用于抽象功能,例如鸟和猫可以抽取一个动物的共性,但是鸟和飞机一般是抽象出一个fly()的行为的接口。

posted @ 2019-12-21 15:06  穿黑风衣的牛奶  阅读(261)  评论(0编辑  收藏  举报