美文网首页
Java抽象类和接口

Java抽象类和接口

作者: 善思者_tin | 来源:发表于2020-01-20 17:27 被阅读0次

    一、抽象类和接口概述

    抽象类和它的子类之间应该是一般和特殊的关系,而接口仅仅是它的子类应该实现的一组规则。

    abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。

    abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,避免使用时在进行抽象类定义时对于 abstract class和interface的选择随意。

    其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。

    二、抽象类和接口语法上的不同

    抽象类

    abstract class Student {   

        abstract void method1();   

        abstract void method2();   

    }   

    接口

    interface Student {   

        void method1();   

        void method2();   

    }   

    在abstract class方式中,Demo可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface方式的实现中,Demo只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说,interface是一种特殊形式的abstract class。

    三、抽象类和接口编程角度不同

    abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。

    其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,不过在JDK1.8中可以使用default关键字实现默认方法。

    interface InterfaceA {

        default void foo() {

            System.out.println("InterfaceA foo");

        }

    }

    在 Java 8 之前,接口与其实现类之间的 耦合度 太高了(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现。这在 lambda 表达式作为Java 8 语言的重要特性而出现之际,为升级旧接口且保持向后兼容(backward compatibility)提供了途径。

    通俗理解

    接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。从设计理念上,接口反映的是 “like-a” 关系,抽象类反映的是 “is-a” 关系。

    抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。

    人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.

    所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。

    四、抽象类和接口的区别

    从设计层面上看,抽象类提供了一种 IS-A 关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。

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

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

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

    4.抽象类里可以没有抽象方法。

    5.从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类,抽象类只能被单继承。

    6.接口中没有 this 指针,没有构造函数,不能拥有实例字段(实例变量)或实例方法。

    7.抽象类不能在Java 8 的 lambda 表达式中使用。

    8.接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。

    9.接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。

    五、抽象类和接口的选择

    使用接口:

    需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法;

    需要使用多重继承。

    使用抽象类:

    需要在几个相关的类中共享代码。

    需要能控制继承来的成员的访问权限,而不是都为 public。

    需要继承非静态和非常量字段。

    面向对象之类名作为返回值类型

    案例

    /*具体类作为返回值类型*/

    class Student {

        public void show() {

            System.out.println("student....show.....................") ;

        }

    }

    // 定义一个类

    class StudentDemo {

        public Student getStudent() {

            return new Student() ;

        }

    }

    // 测试类

    class ReturnDemo {

        public static void main(String[] args) {

            // 创建StudentDemo的对象

            StudentDemo sd = new StudentDemo() ;

            // 调用 public Student getStudent()

            Student s = sd.getStudent() ;

            // 调用方法

            s.show() ;

        }

    }

    面向对象之抽象类名作为返回值类型

    案例

    /*抽象类作为返回值类型*/

    abstract class Animal {

        public abstract void eat() ;

    }

    // 定义一个子类

    class Cat extends Animal {

        public void eat(){

            System.out.println("吃..........................") ;

        }

    }

    // 定义一个类

    class AnimalDemo {

        public static Animal getAnimal() { 

            // Animal a = new Cat() ;

            // return a;

            return new Cat() ;

        } 

    }

    // 测试类

    class ReturnDemo2  {

        public static void main(String[] args) {

            // 调用AnimalDemo的getAnimal这个方法

            Animal a =  AnimalDemo.getAnimal() ;

            // 调用方法

            a.eat() ;

        }

    }

    面向对象之接口名作为返回值类型

    案例

    /*接口作为返回值类型*/

    interface Jump {

        public abstract void jump() ;

    }

    // 定义一个子类

    class JumpImpl implements Jump {

        public void jump(){

            System.out.println("jum....................") ;

        }

    }

    // 定义一个类

    class JumpDemo {

        public static Jump getJump() {

            return new JumpImpl() ;

        }

    }

    // 测试类

    class ReturnDemo3  {

        public static void main(String[] args) {

            // 调用getJump方法

            Jump jump = JumpDemo.getJump() ;

            // 调用

            jump.jump() ;

        }

    }

    六、工作中使用总结

    相关文章

      网友评论

          本文标题:Java抽象类和接口

          本文链接:https://www.haomeiwen.com/subject/kwwczctx.html