我想用比较通俗的方法告诉你:
假如有两个程序员,两个在两个程序里都要用到一种功能,比如要取一个对象名。
甲自己做了一个方法叫getname,乙也作了一个方法叫qumingzi。如果两个人要去看对方的程序,那么这个方法要读懂是不是要有一个过程?
如果在公司里,有个抽象类,离面有个抽象方法较getName,公司规定,凡遇到这样的问题就实现这个方法。那么这两个人要读对方的代码是不是就容易了??
接口:在C++中,一个类可以多重继承的,但是在Java中只能有一个父类,这是Java的一个优点,但是,任何事物都是两面的。他虽然防止了产生C++中的“四不像”但是也限制了一些多重的好处,比如你有西红柿类,现在你要定义一种新的水果,它既有西红柿的属性,但是他的味道象香蕉,怎么办??于是Java提供了接口,这样,香蕉的味道就可以在接口里实现了~~
不知道明白了没有。这是我的理解。没有翻资料,可能有些偏差~~~:)

解决方案 »

  1.   

    给你介绍个东东BRUCE从“抽象化过程”开始讲起,我们都知道,JAVA是面向对象的,也既OOP(Object-oriented Programming)。OOP提供了问题描述问题的能力。这句话有点拗口。我们常常听高手们说(当然也有入门级菜鸟喜欢说,比如我):要把代码写成象诗歌一样,说的便是这个道理。什么叫问题描述问题?就是当你在看代码的时候就觉得是在看汉语作文,程序所要解决的问题,通过这门语言关键字(比方汉字,英语单词)的逻辑组合很人性化的呈现在你的面前了。比如你要描述你的MM的特征,用汇编来做,估计很难,别人读起来也不会认为ADD AX,BX是今天你的MM在脸上加了层粉。而JAVA可以实现。同样的道理,你的JAVA作文(可以理解为一个文件,一个类)只会说:她很美(属性),她很爱我(行为,也既接口),而大师就会说:她象怎么美,她爱我到如何程度,所以大师就说:我这是诗歌,你那是作文。我们只要做好作文就是了,要做到你的程序要让人家看懂。顺便提一句,就象你不看世界名著(JIVE?),光靠新华字典(API帮助?),是写不出好作文一样,你不读大师的CODE,你就不能写出真正意义上的软件。 
    上面我们讲到行为、接口。注意,这里的接口跟本书后面特指的接口不是一回事情,也不应该是方法(C,C++中为FUNCTION),因为我们的JAVA文件还可以是抽象类,可以是接口,所以暂且称之为“行为”(下文中提到的行为,就是书中本章提到的接口)吧。大多数的类,有属性也有行为,只有属性的类,我们往往设计用来存储软件的公共变量。BRUCE还强调一个道理,所谓类(class),也就是一个新的数据型别(datatype)。int,String等为基本型别,用来描述简单的基本的对象,分别为:整型,字符串等。为了描述复杂的对象,我们要自己来设计类,这便是class,便是JAVA文件,便是软件。什么是对象?对象就是属性和行为的统一体。 
    行为规范了你能对对象发出的请求。你的CLASS,也就是对象,也就是MM,你把她设计出来了,而且你很BT,只给她设计了两个行为:爱我()和MAKE爱与我()。那么她便不可能接受其它客户端class(某个帅哥?)的请求,如果在某个class里,你写成了MM.爱F4(),那么编译器就会出错。 
    你理所当然把MM的属性设成美,你不希望别人来改变这个事实,那么,你就要把这个属性定义为private,这样MM便不会在第二天醒来成为传说中的KL。这在第一章里标题为:被隐藏的实施细节。一个属性,有四种修饰符,public,private,protected,空(默认,friendly)。分别代表的意思是任何对象可以访问,本对象内部可以访问,本对象(class)的继承者可以访问,同一个包(package)的其它对象可以访问。 
    我们总是想尽可能地让自己的代码变的简洁,这便需要重复运用实现码。JAVA提供了这种方式,其途径有两种:组合和继承,假设有一个类为A,A有一个行为doSomething(),还有一个类B,不也想do something,那么你可以在B里产生一个方法doSomethingToo( A.doSomething(); )。这叫做组合。继承是另外一种方法,你可以直接用关键词extends,让B继承自A,那么你不用特殊额外表达,B在外界看来也是有doSomething的能力的。那么我们要问,我们什么时候要组合,什么时候用继承呢?BRUCE讲,当B is a A的时候我们用继承。这不太好理解,我们再举个MM的例子。MM具备吃饭(eatYou( 进食;消化))的行为,MM衍生开来有好色的MM、爱打屁的MM等,但她们都是MM,也就是is a的关系,这个时候你要设计好色的MM的时候就用继承,用extends。而GG不是MM,但是GG is like a MM,因为GG也可以吃饭。这个时候我们就不用再去写eatYou()这个方法了,直接在GG这个类里写eatYou( MM.eatYou(); )那么,GG也具备了进食、消化的功能。其实我们要常常用到组合,在程序里,用继承的地方是比较少的。
    在继承当中,有两个特殊行为需要我们关注:覆写(overriding)和重载(overloading)。现在你只需记住:如果base class和derive class的某个方法名称相同,引数相同,则为覆写(overriding),名称相同,引数相异,则为重载(overloading)。 
      

  2.   

    面向对象一个显著的优点就是多形(多态)性。我本来是不想在这第一部分写代码的,但是似乎这个问题用语言表达不够直观,所以就写了个最简单的能说明多形性的问题。看代码先 
    //Love.java 
    class MM{ 
    public void toSeeGG(){ 
    System.out.println("xxx"); 

    } class HaoseMM extends MM{ 
    public void toSeeGG(){ 
    System.out.println("诱惑GG!!!"); 

    } class BenfenMM extends MM{ 
    public void toSeeGG(){ 
    System.out.println("好羞涩哦...."); 

    } public class Love{ 
    public static void loveGG(MM i){ 
    i.toSeeGG(); 

    public static void main(String[] args){ 
    MM mm1 = new HaoseMM(); 
    MM mm2 = new BenfenMM(); 
    loveGG(mm1); 
    loveGG(mm2); 


    该代码运行的结果是: 诱惑GG!!! 
    好羞涩哦.... 我们看到由MM衍生出来有好色MM(HaoseMM),本分MM(BenMM),MM们都可能会看到帅哥,但是好色MM和本分MM看帅哥的眼神是不一样的,如程序中定义。在爱(Love)这个类里,我们定义一个方法loveGG,我们给它传递一个参数,是基类(base class)MM,然后toSeeGG()。通过本文最开头的描诉,我们知道,HaoseMM和BenMM与MM的关系是is a的关系,所以我们在用到loveGG(mm1)和loveGG(mm2)时候编译器不会 
    出错。我们看到,程序自动各自执行了haoseMM和BenfenMM的toSeeGG(),而不是打印出“xxx”。这就是多形性。之所以会如此神奇,是因为JAVA运行时环境提供了动态绑定技术。动态绑定会让你产生的MM在JAVA运行时环境里按照你的指示分别作出行为。OK,我们不需要知道动态绑定是怎么运做的,我们只要知道这是什么,因为我们还在第一章。上溯造型(upcasting)这个概念也在这里被提出来了。在loveGG(MM i)这个方法里,方法接受的是MM,可是loveGG也接受HaoseMM和BenfenMM,这个特性就叫上溯造型。 
      

  3.   

    我们在上面的程序中看到了一句没有用的代码,就是在MM类里的System.out.println("xxx");。没有人关心基类MM是怎么看帅哥,因 为它只是一个模版,所以我们干脆就不要这句代码,而且我们连{}也不要了,直接改写这个方法为public abstract void toSeeGG();,那么这 个方法称做抽象方法(abstract method)。基类MM对我们来说没有实现的必要,于是我们把class MM{...}改写为abstract class MM{...}, 那么这个类叫做抽象类(abstract class)。我们不禁要问,那么抽象类能不能含有非抽象的函数呢。答曰:可以。但是这在实际中没有什么 用处,唯一用到的地方是:1,main()函数,用来测试你的类;2,考试中。那么我们还要问,子类可以不覆写父类中抽象方法行不行?答曰: 如果子类也是abstract,那么可以,否则不行。 比抽象类做的更彻底的是接口(注意,这里的接口是JAVA中真正意义的接口,非上文一开始的接口,也既行为)。接口被设计出来的 目的就是要让你继承的。等………,这是第一章,只让大家知道一些概念就行了,上面我们说的太多了。 BRUCE是个彻底的NN大师,我们接下来看到他把JAVA的低效率问题说的是那么的理所当然,以至于我们看完后情不自禁也要说: 
    恩,JAVA就应该这样做,让C++见鬼去吧。面向对象,于是所有东东都是对象,有对象便有对象的产生和毁灭。程序运行的时候,对象产生在内存中。内存分配有三种策略,分别是静态的,栈式的(stack),和堆式的(heap)。C++使用前两种策略,JAVA仅使用后者。两者有什么区别呢?喜欢寻根究底的朋友请参考本站JSP/JAVA分坛的“栈存储(stack)和堆存储(heap)的区别 ”,我们只要记住,后者在内存中的寻址要花更长的时间,因此JAVA的效率低。但是JAVA提供了根据heap特点产生的垃圾回收机制。垃圾回收机制完成这样的任务,当你的对象不在使用的时候它会自动察觉并消灭。你不用再担心发生内存泄露了。而这是每个C++程序员最头疼的事情。所以,你选择吧,是要安全还是要效率。 
      

  4.   

    至于实际中的应用
    如果你自是写写小东东,没有什么考虑:比如软件工程,软件质量,还有重用性等等
    一般是用不到的
    但是在作“大系统”(好土的说法)时,比如EJB,它对类的命名,方法的实现都有着非常严格的定义和限制,这时候抽象类和接口就派上了用场
    我倒现在,说实话,也是没大用过抽象类~~~~~~~~~~~~~
    不知道别人有什么高见
    毕竟我的水平和经验实在是~~~~~~~~~汗
      

  5.   

    建议看看《java与模式》,里面关于接口和抽象类的用处和益处个人感觉说的很好
      

  6.   

    呵呵!楼上的谦虚了!
    其实,在这里想问的就是为什么?
    个人我觉得接口和抽象类没有表面看起来继承一下就好了那么简单,
    很多时候,接口和抽象类有很大用途的,(因为看到了一些代码对他们的使用)。
    个人觉得他们不是用来继承一下就好了,单方面应用。
    to ai92(抵制日货!!) :你能说一下你“小用”的抽象类吗!仅仅是用了继承吗?
      

  7.   

    还是因为考虑到软件工程、可重用性、出错率等等因素~~~~这些在大公司和较正规的项目里面是有严格限制和要求的
    所以不仅仅为了继承,而是使你的层次更加清晰,代码实现比较工整,为什么呢?因为你要实现这个抽象类,就必须继承它!这样你就是他的一个子类.
    抽象类一般包括的方法和参数也是很泛泛的,他就像楼上有人举得例子一样,它是一系列有共同特性的东西的共性的描述。他的存在就是要说,所有这个纲目里的东西,就必须有我的共性,不然就不是。这样,你写的类是属于哪部分的不就很清楚了?
    你刚才对我的话理解有偏差,我说的“没大用过”是说“基本没有用过”,这是我们这里的一种说法~~~~~~~~:)~
    这是我个人的看法,希望大家指正。还有在《Effective Java》中提倡用接口少用抽象类,我也没仔细看,最近时间紧张啊~~~~~~~~希望能有人提炼一下~~~~~~~~~
      

  8.   

    这个问题好像讨论了很久了!!!!!
      楼上。的确应该相应多接口少抽象的!这个也是java提倡的一种规范!
    毕竟抽象类给我感觉总是不论不类。没有接口的正统!而且接口是一个
    完全的方法声明。
      

  9.   

    关于接口和抽象类的讨论(转)
    http://expert.csdn.net/Expert/topic/2723/2723285.xml?temp=.6804621