抽象类和接口的使用

123 阅读4分钟

抽象类和接口如何选择?

  • 抽象类:抽象类是把相同的东西提取出来,是为了重用;抽象类表示的是什么,这个对象是什么(objects)
  • 接口:接口的作用是提供程序里面固话的规则,是为了降低耦合,这个对象可以做什么(methods)

比如说,学生和老师两个对象。老师和学生都有姓名、年龄、性别等,都会走路,吃饭,但是老师授课,而学生要听课,不同老师教授的课程不一样,不同专业的学生听的课也不同。我们可以把老师和学生共有的属性和方法提取出来,用抽象类表示:

public abstract class Person {
    String name;
    int age;
    String sex;

    abstract void eat();
    abstract void run();
}

老师会授课,不同老师授课不同,我们可以定义一个接口:

public interface Teach {
    void teach(String className);
}

学生要上课,不同专业的学生上的科目不同,我们也可以定义为接口:

public interface TakeClass {
    void takeClass(String className);
}

定义老师:

public class Teacher extends Person implements Teach {

    @Override
    public void teach(String className) {
        System.out.println("teach " + className);
    }

    @Override
    void eat() {
        System.out.println("teacher eat");
    }

    @Override
    void run() {
        System.out.println("teacher run");
    }
}

定义学生:

public class Student extends Person implements TakeClass {

    @Override
    public void takeClass(String className) {
        System.out.println("take class: " + className);
    }

    @Override
    void eat() {
        System.out.println("student eat");
    }

    @Override
    void run() {
        System.out.println("student run");
    }
}

这样使用抽象类和接口,是一种很合理的方式。

现在有很多讨论和建议提倡用interface代替abstract类,两者从理论上可以做一般性的混用,但是在实际应用中,他们还是有一定区别的。抽象类一般作为公共的父类为子类的扩展提供基础,这里的扩展包括了属性上和行为上的。而接口一般来说不考虑属性,只考虑方法,使得子类可以自由的填补或者扩展接口所定义的方法。

就像这个老师和学生的例子,抽象类提取了他们共有的属性,他们各自有什么属性可以交给子类去完成。有人可能会说,为什么不把eat 和 run 方法定义为接口呢?这当然也是可以的。但是我觉得,吃和走,是人自身的一种行为,它不像授课和上课这种是因为某种身份而特有的行为,吃和走与人自身的属性(姓名,年龄)都是【人】本身就有的,所以我觉得一起放到抽象类里更合适一些。当-然,你单独定义一个【人行为】的接口从语法角度讲也没问题

总结:

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现(不讨论java8的情况下)

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现。不能写成abstract void abc(){}。

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

11、从实践的角度来看,如果依赖于抽象类来定义行为,往往导致过于复杂的继承关系,而通过接口定义行为能够更有效地分离行为与实现,为代码的维护和修改带来方便。

12、选择抽象类和接口的时候记得一句话:抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。

13、使用抽象类,要保证和实现类之间是【is-a】关系。

参考资料: www.jianshu.com/p/0c2a163d0…