[原创]关于接口的教程
接口教程By Tempnetbar
欢迎转载,转载请注明出处
很多初学者都对接口的用处非常疑惑,我也曾经苦思冥想了很久,终于悟出来了。除了要告诉大家接口的知识之外我也想建议大家遇到问题自己多多思考,这样才能比较牢固的掌握,多看看现有的资料,我是通过一些设计模式的资料摸到蛛丝马迹的。
好,言归正传。接口究竟有什么用?他的应用主要是在设计模式领域,当然了,这样说可能有点偏颇,因为接口的作用其实是提供你 在不改动原有代码的基础上 增加、改变类的功能。那么为什么在设计模式里应用广泛呢?因为在面向对象的设计原则中有那么一条开放封闭原则,内容大致如下:一个良好的设计应该可以在不改动原有代码或者改动少数代码的基础上增加或者改变原有的功能。因此接口正好符合这一需求。接下来看一下代码实例你就会明白。以下代码是模仿JDBC的设计原则所写的,并不是原代码,但是设计思想是一致的,之所以选择这样一个例子是因为你可以对接口的应用有一个感性的认识,因为JDBC想必大家都会用到。同时对JDBC的理解也能够深入一点。献丑了:
假设read()方法从数据库里读取一个数据。由于不同数据库的读数据的实现方法各有不同,因此Java如何统一这一差异呢?答案是他提供JDBC接口。JDBC是接口同时也是Java访问数据库的规范,数据库厂商根据这个规范来写符合自己数据库产品的JDBC驱动,在使用JDBC时是不是要加载一个对应数据库的驱动呢,记起来了吧?并且你可以看一下Java的API文档,关于java.sql包里的内容,你看到的多数是什么?多数都是接口(文档里以斜体表示)OK,先给大家建立一个暗示,让大家感觉一下接口和JDBC的暧昧关系,呵呵~
好,实例代码goes here:
interface readData
{
object read();
}
好,Sun把JDBC里读取数据的接口定义成这样。那么厂商A在自己产品的JDBC驱动里这样实现:
class dbReader implements readData
{
public object read()
{
//与厂商A数据库相关的读取操作实现
}
}
好了,那么你在你的程序里使用了厂商A的数据库,因此你要用他的JDBC驱动来写程序:
class dbProgram
{
//加载驱动
//调用相应的JDBC方法取得connection等必要对象
object readData=read();//这里的read()方法在JDBC的接口中定义过
}
至此,你完成了对于数据库的读取。到此为止一切顺利。
一天,你的程序由于种种原因要使用厂商B的数据库驱动了(也许是你的客户要求这么做,也许是厂商A倒闭了,他的数据库再也不是主流了)。那么你很幸运,因为你使用Java,你使用JDBC访问数据库。你的代码会如何改动呢?通常如果你的数据库变动的话会造成对代码的巨大变动,但是现在,使用JDBC(注意JDBC是一套接口规范)的话,你只要改变你加载的JDBC驱动就可以了,以下的代码一律不用更改。为什么呢?因为厂商A和B的驱动都符合JDBC规范是吧?因此都实现了readData接口中的read()这个方法对吗?这样虽然你更换了数据库,但是你的程序其实是调用了对应数据库的read()方法,因此你可以不改变读取代码而只是更改要加载的数据库驱动就可以。那么Java又是如何实现动态的调用呢?面向对象的程序中可以这样引用一个实现了某个接口的类的实例:readData rd=new dbReader();//接口名称 变量名=new 实现了接口的类的名称()
调用接口中的方法就可以这样,rd.read()
可以看到,在代码中始终可以用接口类型的变量来引用具体实现他的类。这样的好处是不管类的具体实现怎么变,由于他必须实现接口中定义的方法,所以我们始终可以保证用readData接口类型的变量能够调用到具体实现这个接口的类的read()方法。
上面的例子由于是自己乱编的所以我在以实际的JDBC应用来举个例,希望大家能够彻底的弄懂。
import java.sql.*;
public class first{
public static void main(String args[])
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
URL url=" jdbc:odbc:tic ";
Connection db=DriverManager.getConnection(url,"fisher","yht8125");
Statement sq_stmt=db.createStatement();
String sql_str="select * from tic";
ResultSet rs=sq_stmt.executeQuery(sql_str);
}
在使用JDBC时要指定驱动就是为了能够让JVM用Class.forName来加载对应的驱动,这样就可以保证调用到对应的方法了。Connection和Statement以及ResultSet都是接口,理论上接口里的方法是不能调用的因为都是抽象方法。这里为什么可以呢?因为他们已经引用了一个具体实现他们的类,类里的方法已经是具体的了。这些具体实现的方法就是数据库厂商做的,但是你可以看到无论用什么数据库,调用时的写法都一样,因为方法的名字已经在接口里定义了,这样你的代码就可以不用改变,而实现功能的增加或者替换。
那么我想这其中的奥秘大家应该已经能够体会到了,大家再好好的悟一下吧,相信对接口的用处可以基本了然了,要认识接口的更多应用可以去看设计模式。当然你也可以不局限于模式,接口在你的程序中会发挥更多重要的作用。一般来说如果你的程序中存在变点(在未来功能可能变动的地方)都应该用接口或者是抽象类来实现。这样才能保证以后变动的顺利。
写得不好请大家多多指正!
----------------解决方案--------------------------------------------------------
接口其实是一种规范,是一种人为的规范。
我是不是可以这样理解:它就像是计算机鼠标的插口,不管你用什么牌子的鼠标,只要它遵循这个插口的设计,那么他就可以在这台计算机上使用?
JAVA的接口是不是这个意思?
----------------解决方案--------------------------------------------------------
对了,嘿嘿
----------------解决方案--------------------------------------------------------
感谢tempnetbar的指点.
说实话现在还没彻底理解,回去再好好想想.
----------------解决方案--------------------------------------------------------
不仅限于数据库的应用
----------------解决方案--------------------------------------------------------
哈,大哥你发的这几贴都这么经典,我正好学到这。多亏你这贴哦,让我对接口理解更深了。
哈哈,先谢了。以后可要再多发些经典贴给我们这些初学者。
----------------解决方案--------------------------------------------------------
可以说明一下接口的其它用途吗?比如将对象强制转换为接口,下面是我书上的一个例子,我不理解的是这种用途具体有什么用,在哪种情况下可以用上。 Orange anOrange = new Orange(); Fruit aFruit=(Fruit)anOrange; Fruitlike aFruitlike=(Fruitlike)anOrange; Spherelike aSpherelike=(Spherelike)anOrange;
aFruit.decay(); aFruitlike.squish();
aFruitlike.toss(); aSpherelike.toss();
anOrange.decay(); anOrange.squish(); anOrange.toss(); anOrange.rotate();
----------------解决方案--------------------------------------------------------
虽然我JAVA 学的不怎么的 ,接口这个概念 看来还是理解对了!
----------------解决方案--------------------------------------------------------
接口就是别人写的虚类,你要完成某项工作,可以用该类,然后重写类中的方法就行了,这有什么好说的?
----------------解决方案--------------------------------------------------------
以下是引用marer在2005-7-19 10:06:07的发言:
接口就是别人写的虚类,你要完成某项工作,可以用该类,然后重写类中的方法就行了,这有什么好说的?
宏观和微观,理论和实践的区别而已!
[此贴子已经被作者于2005-7-28 22:48:23编辑过]
----------------解决方案--------------------------------------------------------