java

位置:IT落伍者 >> java >> 浏览文章

澄清Java语言接口与继承的本质


发布日期:2021年02月02日
 
澄清Java语言接口与继承的本质

计算机学院研二的兄弟与我讨论Java一见面几个问题全是关于接口接口有什么用?为什么要用接口?什么时候该使用接口?很庆幸他们不是问我Java如何连接SQL Server或者是如何开发JEE应用这类问题有杀伤力避之则吉今年计算机学院本科有个毕业设计课题是做JME选这个题目的学生在月末都还在苦着脸研究javautil*这个包这个这个……唉

大多数人认为接口的意义在于顶替多重继承众所周知Java没有c++那样多重继承的机制但是却能够实作多个接口其实这样做是很牵强的接口和继承是完全不同的东西接口没有能力代替多重继承也没有这个义务接口的作用一言以蔽之就是标志类的类别(type of class)把不同类型的类归于不同的接口可以更好的管理他们OO的精髓我以为是对对象的抽象最能体现这一点的就是接口为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++javac#等)就是因为设计模式所研究的实际上就是如何合理的去抽象(cowboy的名言是抽象就是抽去像的部分看似调侃实乃至理)

设计模式中最基础的是工厂模式(Factory)在我最近的一个很简单的应用中我想尽量的让我的程序能够在多个数据库间移植当然这涉及很多问题单是如何兼容不同DBMS的SQL就让人头痛我们不妨先把问题简单化只考虑如何连接不同的数据库

假设我有很多个类分别是MysqljavaSQLServerjavaOraclejavaDBjava他们分别连接不同的数据库统一返回一个Connection对象并且都有一个close方法用于关闭连接只需要针对你的DBMS选择不同的类就可以用了但是我的用户他会使用什么数据库?我不知道我希望的是尽量少的修改代码就能满足他的需要我可以抽象如下接口

package orgbromontest;

public interface DB

{

javasqlConnection openDB(String urlString userString password);

void close();

}

这个接口只定义两个方法没有任何有实际意义的代码具体的代码由实作这个接口的类来给出比如Mysqljava

Package orgbromontest;

import javasql*;

public class Mysql implements DB

{

private String url=jdbc:mysql:localhost:/test;

private String user=root;

private String password=;

private Connection conn;

public Connection openDB(urluserpassword)

{

//连接数据库的代码

}

public void close()

{

//关闭数据库

}

}

类似的当然还有Oraclejava等等接口DB给这些类归了个类在应用程序中我们这样定义对象

orgbromontestDB myDB;

使用myDB来操作数据库就可以不用管实际上我所使用的是哪个类这就是所谓的原则但是问题在于接口是不能实例化的myDB=new DB()这样的代码是绝对错误的我们只能myDB=new Mysql()或者myDB=new Oracle()麻烦了我还是需要指定具体实例化的是哪个类用了接口跟没用一样所以我们需要一个工厂

package orgbromontest;

public class DBFactory

{

public static DB Connection getConn()

{

Return(new Mysql());

}

}

所以实例化的代码变成myDB=DBFactorygetConn()

这就是种模式中最基础的普通工厂(Factory)工厂类负责具体实例化哪个类而其他的程序逻辑都是针对DB这个接口进行操作这就是针对接口编程责任都被推卸给工厂类了当然你也可以继续定义工厂接口继续把责任上抛这就演变成抽象工厂(Abstract Factory)

整个过程中接口不负责任何具体操作其他的程序要连接数据库的话只需要构造一个DB对象就OK而不管工厂类如何变化这就是接口的意义抽象

继承的概念不用多说很好理解为什么要继承呢?因为你想重用代码?这绝对不是理由继承的意义也在于抽象而不是代码重用如果对象A有一个run()方法对象B也想有这个方法所以有人就Class B extends A这是不经大脑的做法如果在B中实例化一个A调用A的Run()方法是不是可以达到同样的目的?如下

Class B

{

A a=new A();

arun();

}

这就是利用类的聚合来重用代码是委派模式的雏形是GoF一贯倡导的做法

那么继承的意义何在?其实这是历史原因造成的最开始的OO语言只有继承没有接口所以只能以继承来实现抽象请一定注意继承的本意在于抽象而非代码重用(虽然继承也有这个作用)这是很多Java烂书最严重的错误之一它们所造成的阴影我至今还没有完全摆脱坏书害人啊尤其是入门类的流毒太大什么时候应该使用继承?只在抽象类中使用其他情况下尽量不使用抽象类也是不能实例化的它仅仅提供一个模版而已这就很能说明问题

软件开发的万恶之源一是重复代码而不是重用代码二是烂用继承尤以c++程序员为甚Java中取缔多重继承目的就是制止烂用继承实是非常明智的做法不过很多人都不理解Java能够更好的体现设计这是让我入迷的原因之一

上一篇:面向Java开发人员的Scala指南: 包和访问修饰符

下一篇:Java中的String、StringBuffer和Math类