抽象类与接口

191 阅读4分钟

抽象类与接口

概述:面向对象的设计,复用的重点在于抽象层的复用,而不是某一个具体代码块的复用,这里涉及到两个概念:1.抽象类,2.接口。下面对其进行解析。

抽象类

概念:抽象类是对根源的抽象。在普通类的基础上添加了抽象方法,抽象方法是指没有方法体的方法,抽象方法需要加上abstract关键字,同时类中包含了抽象方法也需要用abstract修饰。


使用原则

  1. 抽象方法访问修饰符必须为publicprotected(若为private,则不能被子类继,子类则无法实现该方法),缺省情况下默认为public
  2. 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理。
  3. 抽象类需要用abstract关键字修饰,类中的抽象方法也需要用abstract修饰。
  4. 抽象类中定义的抽象方法必须在具体子类中实现,若子类没有实现抽象父类中的所有抽象方法,则子类也为abstract类型。

易错点:

  1. 抽象类中可以存在构造方法,其存在目的是属性的初始化,并且子类对象实例化时,依然满足先执行父类构造,再执行子类构造的顺序。
public class abstractClass {
    public static void main(String[] args) {
        A a = new B();
        a.fun1();
    }
}
abstract class A{
    public A(){
        a = 1;
        System.out.println("A构造方法");
    }
    int a;
    public abstract void fun1();
}
class B extends A{
    public B(){
        System.out.println("B构造方法");
    }

    @Override
    public void fun1() {
        System.out.println(a);
    }
}
打印结果:A构造方法 B构造方法 1
  1. 抽象类不可以用final关键字声明。(因为抽象类必须有子类,而final定义的类不允许被继承)。
  2. 抽象类"可以"使用static声明。
    1. 外部抽象类不能使用static声明
    2. 内部抽象类可以使用static声明
public class abstractClass {
    public static void main(String[] args) {
        A.B b = new C();
        b.fun1();
    }
}
//编译器报错
static abstract class A{};

abstract class A{
    static abstract class B{
        public abstract void fun1();
    }
}
class C extends A.B{

    @Override
    public void fun1() {
        System.out.println("static静态内部类");
    }
}
打印结果:static静态内部类
  1. 可以直接通过类名.方法的方式调用抽象类中的static方法。
public class abstractClass {
    public static void main(String[] args) {
        A.fun1();
        B.fun1();
    }
}
abstract class A{
    public static void fun1(){
        System.out.println("static方法");
    };
}
class B extends A{

}
打印结果:static方法 static方法
  1. 抽象类中定义的抽象方法必须在具体子类中实现,因此,不能有抽象构造方法或抽象静态方法。
  2. 抽象类中的静态成员变量中的访问类型可以任意。

接口

概念:接口是对动作的抽象,使用interface关键字进行声明,接口中所有方法都必须是抽象的。接口中方法定义默认为public abstract类型,接口中的成员变量类型默认为public staitc final


使用原则

  1. 接口只能对方法进行声明,不能有具体的实现。
  2. 接口可以继承接口,甚至可以继承多个接口。
  3. 接口需要用interface关键字修饰。
  4. 接口中定义的方法必须在具体子类中实现,若实现类没有实现接口中的所有抽象方法,则子类也为abstract类型。
  5. jdk1.8中,可以使用default修饰方法,可以避免其他实现类的修改(需要在接口中实现方法体)。
  6. 在jdk1.8中,新增了static函数,使用static修饰的方法也是抽象方法,拥有自己的方法体,可以使用接口名.方法名()的形式调用。

public class abstractClass {
    public static void main(String[] args) {
        new A().fun1();
        System.out.println(new A().fun2());
        new A().fun3();
        i.fun4();
    }
}
interface i{
    void fun1();
    String fun2();
    default void fun3(){
        System.out.println("fun3");
    };
    static void fun4(){
        System.out.println("fun4");
    };
}
class A implements i{

    @Override
    public void fun1() {
        System.out.println("fun1");
    }

    @Override
    public String fun2() {
        return "fun2";
    }
}
打印结果:fun1 fun2 fun3 fun4

抽象类与接口的异同

相同点:

1.接口和抽象类都不能实例化 2. 都位于继承的顶端,用于被其他实现或继承 3. 都包含抽象方法,其子类必须覆写这些抽象方法

不同点:

抽象类接口
声明关键字abstractinterface
构造器可以有构造器不能有构造器
访问修饰符任意访问修饰符默认为public,不允许定义为private或protected
多继承关系一个类最多只能继承一个抽象类一个类可以实现多个接口
字段声明抽象类的字段声明可以是任意的字段默认为static和final的