看上面一篇可以理解的就好了,我这里是按照自己的理解,啰嗦的进行一下表述。
如果是偶尔阅读到这里,这个不算,我们假设你是主动搜索相关关键字看到的这里。那么,好,我们就有了一个你使用过多次相关类的经验的前提,你很可能疑惑这个问题:在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,那为什么要有两种呢?
还是要强调一下,假设读者是有使用经验的。
开始!这是个通过李雷和韩梅梅的爱情故事来理解的例子。
先上包结构
定义了Man.class和Woman.class两个抽象(abstract)类,代码如下:
package abstracts;
public abstract class Man {
public abstract String adamsApple();
public abstract String beard();
public abstract String peeStand();
protected boolean canGiveBirthToAChild(){
return false;
}
}
package abstracts;
public abstract class Woman {
public abstract String bigChest();
public abstract String longHair();
public abstract String peeSquat();
protected boolean canGiveBirthToAChild(){
return true;
}
}
然后定义一个Characteristic接口(interface)类:
package interfaces;
public interface Characteristic {
//外部特征
void appearance();
//毛发
void hair();
//嘘嘘
void pee();
}
接下来主角要出场了,先上韩梅梅:
package someone;
import interfaces.Characteristic;
import abstracts.Woman;
public class HanMeimei extends Woman implements Characteristic{
//大湿胸
public String bigChest() {
// TODO Auto-generated method stub
return "D cup is my pride";
}
//长发
public String longHair() {
// TODO Auto-generated method stub
return "dai wo chang fa ji yao";
}
//呵呵
public String peeSquat() {
// TODO Auto-generated method stub
return "hahahaha";
}
public void appearance() {
System.out.println(bigChest());
}
public void hair() {
System.out.println(longHair());
}
public void pee() {
System.out.println(peeSquat());
}
}
这里我们直接调用abstract实现方法的值,不要问我为什么,就是想,当然也可以直接打印的。没什么毛病,继续李雷:
package someone;
import interfaces.Characteristic;
import abstracts.Man;
public class LiLei extends Man implements Characteristic{
/**
* 小趣闻:喉结的英语是亚当的苹果,跟圣经里亚当偷吃苹果有关,
* 神奇的是卡个苹果居然没噎死
*/
public String adamsApple() {
// TODO Auto-generated method stub
return "I hava an adam`s apple";
}
//胡须
public String beard() {
// TODO Auto-generated method stub
return "I have to fix beard everyday";
}
//站着撒尿
public String peeStand() {
// TODO Auto-generated method stub
return "need a little time";
}
public void appearance() {
System.out.println(adamsApple());
}
public void hair() {
System.out.println(beard());
}
public void pee() {
System.out.println(peeStand());
}
}
除了abstract过来的方法名以外,大同小异。
这个时候,我们到知道如果想打印信息可以通过接口这样测试:
也可以这样测试:
到了这里,好像整体来看也没什么异常,好,那我们反过来看:
就单纯看上面这张图,我们改怎么描述HanMeimei?无非两种:
1.HanMeimei是个带有特征的女人;
2.HanMeimei是带有女人的特征?
感觉来看1是靠谱的,同样的LiLei解释为“有特征的男人”是合适的。
如果你思维够缜密,你会发现这只是我用语文来强词夺理,如果把两个抽象的类换一下名字,2的说法就成了合理的。换个角度。
如果再细心点,上面给出代码的类对比开始的结构图中似乎少了LiHua的存在。
如果LiHua是这样的:
Lihua是特征?Lihua有特性?似乎都可以,那么再看:
很显然,LiHua有特征,有爱好这样更说的通一些。但是这个时候,LiHua的本征是什么?我们是不知道的。LiHua是HanMeimei生的(当然LiLei也是很关键的),那我们让LiHua extend HanMeimei好了!也不对啊,从人物设定来讲LiHua不是某个HanMeimei,这个逻辑是不通的。在这里的关系中,需要给Lihua一个本征的定义,就只能是extend Man 或者Woman了。
为什么要这样呢?因为abstract类只允许继承一个,而interface允许实现多个。这个“单”和“多”的限制,就要求了在进行抽象时,abstract类更倾向本征性质的内容,而interface则侧重功能的引入。
abstract Class倾向本征,isA的概念;interface倾向于功能,likeA的概念。
再然后呢?你可以随便选个性别让他/她继承一下。