Java 接口

 

Java 接口(重要)

 

基本定义:

 

       如果一个类中只有抽象方法和全局常量所组成;在这类情况下不会将其定义为抽象类,而只会将其定义为“接口”;严格来讲:接口就属于一个特殊的类,而且这个类里面只有抽象方法和全局常量(无构造方法)

 

         接口定义需要使用interface  关键字。

 

 

 

interface A { //定义接口interface

         //接口中主要有全局常量和抽象方法组成

         public static final String MSG = "Hello" ;          // 全局常量

         public abstract void print() ;              // 抽象方法

}

 

 

 

由于接口里面存在有抽象方法,所以接口不可进行对象实例化(new

 

1、  接口必须要有子类,但是此时一个子类可以使用implements关键字实现多个接口

 

2、  接口的子类(不是抽象类),必须要覆写接口中的全部抽象方法

 

3、  接口的对象可以利用子类对象的向上转型进行实例化操作

 

interface A { //定义接口interface

         //接口中主要有全局常量和抽象方法组成

         public static final String MSG = "Hello" ;          // 全局常量

         public abstract void print() ;              // 抽象方法

}

interface B {

         public abstract void get() ;

}

class X implements A,B { //X类是实现了AB两个接口功能

         public void print() {

                   System.out.println("A") ;

         }

         public void get() {

                   System.out.println("B") ;

         }

}

public class Demo {

         public static void main(String [] args) {

                   X x = new X() ;  //实例化子类对象

                   A a = x ;    // 向上转型

                   B b = x ;    // 向上转型

                   a.print() ;

                   b.get() ;

         }

}

 

 

 

public class Demo {

         public static void main(String [] args) {

                   A a = new X() ;//实例化子类对象

                   B b =(B) a ;        // 向下转型

                   b.get() ;

         }

}

 

实际上 AB接口没有直接联系,但是两个接口拥有同一个子类X;因为最终实例化的是X子类,而子类属于B类的对象,所以以上的Demo代码是可行的。

 

 

 

对于子类而言除了接口之外,还可能会继承抽象类,所以说一个子类又要继承抽象类又要实现接口的化;先使用extends实现继承,再使用implements实现接口

 

interface A { //定义接口interface

         //接口中主要有全局常量和抽象方法组成

         public static final String MSG = "Hello" ;          // 全局常量

         public abstract void print() ;              // 抽象方法

}

interface B {

         public abstract void get() ;

}

abstract class C {

         public abstract void change() ;

}

class X extends C implements A,B {

 //X类是先继承C类再实现了AB两个接口功能

         public void print() {

                   System.out.println("A-implements") ;

         }

         public void get() {

                   System.out.println("B-implements") ;

         }

         public void change() {

                   System.out.println("C-extends")

         }

}

 

 

 

对接口而言组成的内容就是抽象方法和全局常量,所以很多的时候也有一些人为了省略,可以不用写上 abstract public static final 声明;并且再方法上是否写public结果都是一样的,因为再接口中只能够使用唯一的public访问权限。

 

接口定义的不同

完整

interface A {

         public static final String MSG = "Hello" ;

         public abstract void fun () ;

}

简短

interface A {

         String MSG = "Hello" ;

         public void fun () ;

}

 

**在接口定义抽象方法时可省去public但为了防止访问权限的报错和混淆,不建议省去**

 

 

 

一个抽象类只可以继承一个抽象类,但是反之:一个接口却可以使用extends关键字同时继承多个接口(接口不可以继承抽象类)

 

interface A {

         public void funA() ;

}

interface B {

         public void funB() ;

}

interface C extends A,B {

         // C接口同时继承了AB两个接口

         public void funC() ;

}

class X implements C {

         //由于 C接口包含了AB接口,故X子类继承的接口包括ABC三个

                   //实现覆写

         public void funA() { }

         public void funB() { }

         public void funC() { }

}

 

从继承关系角度:抽象类的限制比接口多;

 

         一个抽象类只能够继承也给抽象的父类,而接口没有这个限制

 

         一个子类只能够继承一个抽象类,却可以实现继承多个接口

 

         Java接口主要功能就是解决了继承的单继承局限问题

 

 

 

虽然接口的定义是只包含定义抽象方法和全局常量,但是所有的限制是不受内部的影响;所以再接口中也可以定义普通内部类、抽象内部类、内部接口

 

interface A {

         public void funA() ;

         abstract class B {

                   public abstract void funB () ;

         }

}

class X implements A {     // x实现A接口

         public void funA() {  

                   System.out.println("A") ;

         }

         class Y extends B {   //内部抽象类的子类

                   public void funB() {}

         }

}

 

**在一个接口的内部如果使用了static定义内部接口,等同一个外部接口

 

interface A {

         public void funA() ;

         static interface class B {//Static定义的内部接口 == 外部接口

                   public abstract void funB () ;

         }

}

 

class X implements A.B {              // x实现A.B接口

         public void funB() {  }

}

 

 

 

1)接口再实际开发中三大核心作用:

 

       定义不同层之间的操作标准

 

       表示一种操作的能力

 

       表示将服务端的远程方法视图暴露给客户端

 

 

 

标准定义:(定义不同层之间的操作标准)

 

         Java中,也存在程序标准,而标准就是由接口定义的;通俗的理解为:接口类即是一个标准,子类则依靠接口类而产出的依赖(接口)

 

//标准可以连接不同层的操作类

interface USB {     //定义标准一定就是定义接口

         public void start() ;

         public void stop() ;

}

class Computer {

         public void plugin(USB usb) { //USB标准插入

                   usb.start() ;      // 调用方法

                   usb.stop() ;

         }

}

class Flash implements USB {

         public void start() {

                   System.out.println("U盘开始使用") ;

         }

         public void stop() {

                   System.out.println("U盘停止使用") ;

         }

}

class Print implements USB {

         public void start() {

                   System.out.println("打印机开始工作") ;

         }

         public void stop() {

                   System.out.println("打印机停止工作") ;

         }

}

 

public class Demo {

         public static void main(String [] args) {

                   Computer com = new Computer() ;

                   com.plugin(new Flash()) ;

                   com.plugin(new Print()) ;

         }

}

 

 

 

工厂设计模式:Factory

 

interface Fruit {

       public void eat() ;

}

class Apple implements Fruit {

       public void eat() {

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

       }

}

 

public class Demo {

       public static void main(String [] args) {

              Fruit f = new Apple() ;

              f.eat() ;

       }

}

interface Fruit {

       public void eat() ;

}

class Apple implements Fruit {

       public void eat() {

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

       }

}

class Orange implements Fruit {

       public void eat() {

              System.out.println("Orange...")

       }

}

public class Demo {

       public static void main(String [] args) {

              Fruit f = new Orange() ;

              f.eat() ;

       }

}

 

Java过程中,最需要关心的就是如何取得一个Fruit接口对象,而不是关心对象是被谁实例化的。

 

一旦子类进行扩充,main的操作和实例化+调用则会发生变化。

 

 

 

interface Fruit {

       public void eat() ;

}

class Apple implements Fruit {

       public void eat() {

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

       }

}

class Orange implements Fruit {

       public void eat() {

              System.out.println("Orange...")

       }

}

class Factory {    // 工厂类

       public static Fruit getInstance(String className) {//static申明则不需要实例化

              if ( "apple".equals(className)) {

                     return new Apple() ;

              } else if ( "orange".equals(className)) {

                     return new Orange() ;

              } else {

                     return null ;

              }

       }

}

public class Demo {

       public static void main(String [] args) {

              // 借由调用工厂类,main看不见子类了,通过工厂类实现调用子类的功能

              Fruit f = Factory.getInstance("apple") ;

              f.eat() ;

       }

}

 

子类对于mian完全透明,所有接口对象都是通过Factory类(工厂类)取得的,如果日后要扩展新的子类对象,则只需要修改工厂类即可,但是客户端调用则不会发生变化。

 

       Fruit f = Factory.getInstance(****) ;中只需要给工厂类传递调用子类名即在工厂类通过if判断调用的子类名进行对子类进行调用操作。

 

 

 

 

 

 

 

 

       main可以看见接口类和工厂类,接口类可以看见子类和子类方法,工厂类可以调用子类和子类方法;main通过调用工厂类而使用接口子类。

       总结:即是通过工厂类实现对接口子类的操作,在子类发生变化时只需要改变工厂类代码即可,不需要对main客户端进行过多承重的代码设计(不需要再一一对接口子类声明实例化)

 

 

 

代理设计模式:

 

interface Subject {    // 接口类核心

       public void make() ;

}

class RealSubject implements Subject {   //核心主题

    public void make() {

       System.out.println("核心主题") ;

    }

}

class ProxySubject implements Subject {    // 代理主题类

    private Subject subject ;

    //子类构造 == 接收一个核心的操作对象

    public ProxySubject(Subject subject) {

       this.subject = subject ;

    }

    public void prepare() {

       System.out.println("核心主题操作准备") ;

    }

    public void make() {

       this.prepare() ;

       this.subject.make() ;

       this.destroy() ;

    }

    public void destroy() {

       System.out.println("核心主题操作结束") ;

    }

}

public class Demo {

       public static void main(String [] args) {

              Subject sub = new ProxySubject(new RealSubject());

              sub.make() ;

       }

}

 

代理设计模式的核心在于有一个主题操作接口(可能有多种方法);核心业务主题只完成核心功能;而代理主题负责完成与核心业务有关的操作。

 

 

 

 

 

抽象类与接口的区别:

 

区别

抽象类

接口

关键字

abstract class

interface class

组成

构造方法、普通方法、抽象方法、static方法、常量、变量

抽象方法、全局常量

子类使用

class 子类 extends 抽象类

class 子类implements 接口

子类关系

抽象类可以实现多个接口

接口不可以继承抽象类

但可以继承多个父类接口

权限

可以使用三类权限

仅可以使用public权限

限制

只能继承一个抽象类(单继承)

可以实现多个接口

子类

抽象类和接口都必须有子类,子类必须要覆写全部的抽象方法

实例化对象

依靠子类对象的向上转型进行对象的实例化

 

       经过比较发现:抽象类中支持的种类绝对要高过接口支持的种类;但是抽象类的单继承局限,导致抽象类的缺点大于优点以及接口的引用高于抽象类。

 

n  在进行公共操作的时候,一定要定义出接口

 

n  有了接口就需要利用子类完善方法

 

n  自己写的接口,不要关键字new直接实例化接口子类(用工厂类完成)

 

 

 

 

 

 

 

 

posted @ 2019-04-30 12:11  Mirror王宇阳  阅读(121)  评论(0编辑  收藏  举报