在JAVA里说接口,有两个意思。广义的意思:一个 类/软件实体 对外提供的方法的集合,而狭义的意思就是关键字 interface 所代表的JAVA里特有的一种概念。如果您看到这里就明白了,那可以不用往下看了,我不想班门弄斧!

    何为“对外提供的方法的集合”?第一次看到这个廉洁时我也很纳闷,不急!如果你有一些软件工程的知识,那么下面的这些你一定不会陌生:一个软件实体应尽可能滴做到“高内聚,低耦合”!而做到低耦合的一个方法就是向外界提供一个窄接口!OK!终于出现了“接口”二字。这个概念在软件工程中,也就是要比JAVA还早一些就有了的东西,好了,先解释清楚了它不是JAVA的“特产”!

    鉴于我对其它对象语言的完全无知,在此还是以JAVA说法。
    在JAVA里有四个访问权限,分别由三个访问修饰符和一个缺省修饰符确定。一般而言,一个类的成员变量都被用 private 修饰,而成员方法的修饰符多看设计者的意图了( static 修改的是类××,而不是成员××,一般都是用 public 修饰)。那么我下面的这个说法应该是没有问题的: private 是不向外提供的, protected 修饰的方法是对子类提供的访问接口,不加修饰符的方法是对本包中其它类提供的访问接口,而 public 修饰符的方法是对所有类提供的访问接口。
    我想要是我的表达不是太次的话,那就把接口的第一个意思描述清楚了。且慢,我再多嘴两句。
    看别人的代码总是那么容易,但当你自己写东西的时候一定要注意了,应该尽量少用 public 来修饰你写的方法!能不用就不能,可以用 private 的时候就要坚决用它!举一个很简单的例子。在开发初期,你对此没什么概念,生怕哪个方法别的类用不到,狂用 public ,等开发基本结束开始复审时,麻烦来了,你发现某一个工具类的一些方法不应该公开,但一开始时公开了,导致了一系列的地方对它引用了,试问,此时的你会选择哪条路呢?把引用的地方一个个地改过来,还是让这个恶性肿瘤继续扩大?有一句老话是没错滴:病是早医好!如果当初你就把牢给补上,那今天就不会有那么多的狼来偷你的羊了!

    好了,现在说 interface 。

    如果你的记性不差,那想想你看JAVA书时他是怎么说的。为了克服多重继承带来的麻烦,JAVA取消了C++里的多继承,而用接口来代替。接口没有消除多继承的好处但去掉了多继承带来的坏处!似乎很神奇哦,但,别被它吓到了。

    先看这一些代码:

public abstract class Parent{
    
public void display(){
        System.
out.println("Parent.Display()");
    }

}

public class Child1 extends Parent{
    
public void display(){
        System.
out.println("Child1.Display()");
    }

}

public class Child2 extends Parent{
    
public void display(){
        System.
out.println("Child2.Display()");
    }

}

public class Client{
    
public static void main(String[] args){
        Parent obj; 
// 引用!只是一个引用! Parent 是 obj 的静态类型。

        obj 
= new Child1(); // Child1 是 obj 的动态类型,实际类型。
        obj.diaplay(); // 按照多态,这里调用的是 Child1 里的方法

        obj 
= new Child2(); // 不多说了
        obj.diaplay(); // ..
    }

}

    这些代码没有涉及到接口,设计了一个抽象类用于被继承,而这些代码会输出什么呢?只要你有一些多态的概念,这么简单的问题绝对难不倒你的,呵呵。只是为了演示一下而以。
    而其实在这里呢, Parent 里的那个方法永远调用不到,因为这是一个抽象类,不能被实例化,这个方法在这里是多此一举了。
    不是说接口是用来克服“多继承”带来的坏处的吗,这里没有多继承,但,用它来代替继承一样是没有问题的。
    说做就做:
public interface Parent{
    
public void display();
}
    子类也很好办:
public class Child1 implements Parent{
    
public void display(){
        System.
out.println("Child1.Display()");
    }

}

public class Child2 implements Parent{
    
public void display(){
        System.
out.println("Child2.Display()");
    }

}


    可以看到,只是简单滴把 extends 改写成 implements 就是了。而客户端的代码是完全一样的。当然,运行的效果也是一样的。
    说到这里,我想您大概会觉得好肤浅,其实,我想要的效果也就差不多是这样了。

    如果你觉得不够过瘾,没事,理解了就最好。这里还有个例子。我将向你展示接口的另一种理解方法。
    假设我们要实现一个从 1 加到 N 的程序,你会说, it's so easy. 于是

public class Sum{
    
public int sum(int n){
        
int sum = 0;
        
for(int i = 0; i <= n; i++)
            sum 
+= i;
        
return sum;
    }

}

    是这样,没错,很简单,这样确实是实现了。但是,假如,万一,你不是个“程序员”,你是管程序员的,你想你手下的某个程序员A 为你实现这个功能,但是,你还给了另外一个程序员B 其它的任务,而在 B 的任务里,就有用到 A 要实现的功能。而且你知道,A 目前在公司的地位不是很高,他想表现自己。也许,他会拿给你一些艺术代码,可你想要的只是那个功能。现在,你怎么办呢?
    办法还是很简单,你只要给 A 一个接口,并把功能说清楚就可以了。
public interface Sum{
    
public int sum(int m, int n);
}

    那么 B 那儿他也放心地写了,因为他要的也只是一个功能,而不是具体的实现,A 也可以放开他想像的翅膀了。最后他给了你两个代码:
public class SumImp1{
    
public int sum(int m, int n){
        
int sum = 0;
        
for(int i = m; i <= n; i++)
            sum 
+= i;
        
return sum;
    }

}

public class SumImp2{
    
public int sum(int m, int n){
        
if(n >= m){
            
return sum(m, n - 1+ n;
        }
else{
            
return m - 1;
        }

    }

}


    其实他给的你什么代码你并不会关心,你只是知道了,我要的功能有了,这就好了。接口,这就是它给你带来的好处。
    那么,从这里,你是不是体会到了另一种理解接口的思路呢?

    接口,可以把它说成是一个协议,意思即:你要用我的东西,你就必须遵守我的规定!像上面那样,B 要使用接口 Sum 的功能,他只有一个方法来调用它:

    Sum s = new SumImp1(); int sum = s.sum(1, 100);
        s = new SumImp2();     sum = s.sum(1, 100);

    接口的好处就在这里体现出来了。s 只是一个引用,它的静态类型是 Sum ,而动态类型则可以被你支配!在这里,你可以调用 SumImp1 ,也可以用 SumImp2 ,随你的高兴就是了。但 s.xxx(),这里的 xxx() 一定是在 Sum 里定义的,而在 SumImp1 或者 SumImp2 里定义的其它一切对于 s 来说都是不可见的。所以,用接口可以很好地限制与外部的耦合,而且基本上是一劳永逸的做法,一开始定义好一个接口,以后没有了一点担心的必要!


    到这里,我算是说完了,朋友,你要是觉得我说得不差,那记住就行了。但如果你觉得没明白,可以留言,我尽全力把我知道的都说出来,但愿我理解的不是错的。
    如果你觉得我哪里说错了,那请您把我错在哪里指出来,相互讨论自己的所好,于我而言,实在是人生一大乐事矣!