`
TonyLian
  • 浏览: 402092 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【讨论】使用骨架实现类后子类是否还要实现接口

阅读更多

这里要讨论的是,接口、抽象类、普通类 三者的一个组合:

首先是,接口定义了功能性的方法;
然后,一个抽象类实现了这个接口,作为骨架实现类,它完成了接口的一部分实现(默认实现)
最后是一个普通类,继承自这个抽象的股价实现类,并完成了抽象类中未实现的方法。

 

接口:

public interface 交通运输able {

    void 装货();

    void 卸货();

    void 运输();

}

 

抽象类:

public class 卡车 implements 交通运输able  {

    public void 运输() {
         .....
    }

}

 

子类:

public class 某型号卡车 extends  卡车  {

    public void 装货(){
       .....
    }

    public void 卸货(){
       .....
    }
}

 

 

 以上是我给出的代码。

 

现在要考虑(或者说犹豫、疑惑)的地方是在 子类 的定义中,是否还要明示 实现 接口 ?

public class 某型号卡车 extends 卡车 implements 交通运输able {

开始我的想法是,不需要 的。因为:

1)作为父类的那个抽象类已经实现了接口,子类自然就已经实现了。

2)如果我只将这个抽象类类对外开放(允许他人扩展自己的各种卡车去)的话,可以把 接口 作为“包级私有”类封装起来。这样可以很方便日后为接口增加新的方法,只要确保新增的方法,在抽象类中都提供默认实现就可以了。

     而如果向上一行这样使子类也明示实现接口的话,就需要将接口公有化。那么日后就没法增加新方法了。(因为你不知道已经有多少人实现了这个接口,你一增加新方法,他们必须相应地增加实现)

 

似乎在“子类中也明示实现接口”是对自己的禁锢。但是,我之所以要发这个帖子请大家讨论的原因是,我看了 List、AbstractList、ArrayList 这三个源码。

 

恰恰在 AbstractList 已经实现了 List 接口的情况下,其子类 ArrayList  仍然明示的实现了 List 接口。我不知道这是一种严谨的做事风格呢?还是作者出于对自己的充分自信呢(List接口日后肯定不会扩充新方法了!)?

 

欢迎大家讨论。

 

分享到:
评论
18 楼 TheMarine 2009-05-28  
我对于骨架类的理解是:使得具体子类只专注于自身的特定方法实现,忽略自身不会提供的方法(对于自身的冗余方法).简单说就是没必要一个个实现接口的所有方法,要调用就调用骨架类的.而这里ArrayList不允许忽略任何list接口的方法,必须自己去小心实现每个方法.当有某类只继承abstractlist,那就方便了,只要改写需要改写的部分.
17 楼 tenderuser 2009-05-24  
感觉有学到东西了,关于这个方面的东西还没有什么深入了解,以后慢慢来吧
16 楼 拥抱变化之美 2009-05-21  
我想ArrayList的实现者Joshua应该是这个意思:就是AbstractList可以用来实现包括List在内的多个接口,例如,IDemo,等等。尽管ArrayList扩展了AbstractList类,但不一定要实现所有的接口,它可以根据自身的需要只实现部分接口,比如List接口。

看看下面我写的代码,是不是这个意思:

interface IFoo{
void foo();
}

interface IBar{
void foo();
void bar();
}

abstract class AbstractFoo implements IFoo ,IBar {
private String val ;
public void setVal(String val) {
this.val = val;
}
public String getVal() {
return val;
}
}

public class FooBar extends AbstractFoo implements IFoo {

public void foo() {
}

public void bar() {
}

public static void main(String[] args){

}
}
15 楼 seemoon 2009-05-16  
<div class="quote_title">TonyLian 写道</div>
<div class="quote_div">
<p>这里要讨论的是,接口、抽象类、普通类 三者的一个组合: <br><br>首先是,接口定义了功能性的方法; <br>然后,一个抽象类实现了这个接口,作为骨架实现类,它完成了接口的一部分实现(默认实现) <br>最后是一个普通类,继承自这个抽象的股价实现类,并完成了抽象类中未实现的方法。</p>
<p> </p>
<p>接口:</p>
<pre name="code" class="java">public interface 交通运输able {

    void 装货();

    void 卸货();

    void 运输();

}
</pre>
<p> </p>
<p>抽象类:</p>
<pre name="code" class="java">public class 卡车 implements 交通运输able  {

    public void 运输() {
         .....
    }

}
</pre>
<p> </p>
<p>子类:</p>
<pre name="code" class="java">public class 某型号卡车 extends  卡车  {

    public void 装货(){
       .....
    }

    public void 卸货(){
       .....
    }
}
</pre>
<p> </p>
<p> </p>
<p> 以上是我给出的代码。</p>
<p> </p>
<p>现在要考虑(或者说犹豫、疑惑)的地方是在 子类 的定义中,是否还要明示 实现 接口 ?</p>
<pre name="code" class="java">public class 某型号卡车 extends 卡车 implements 交通运输able {
</pre>
<p>开始我的想法是,不需要 的。因为:</p>
<p>1)作为父类的那个抽象类已经实现了接口,子类自然就已经实现了。</p>
<p>2)如果我只将这个抽象类类对外开放(允许他人扩展自己的各种卡车去)的话,可以把 接口 作为“包级私有”类封装起来。这样可以很方便日后为接口增加新的方法,只要确保新增的方法,在抽象类中都提供默认实现就可以了。</p>
<p>     而如果向上一行这样使子类也明示实现接口的话,就需要将接口公有化。那么日后就没法增加新方法了。(因为你不知道已经有多少人实现了这个接口,你一增加新方法,他们必须相应地增加实现)</p>
<p> </p>
<p>似乎在“子类中也明示实现接口”是对自己的禁锢。但是,我之所以要发这个帖子请大家讨论的原因是,我看了 List、AbstractList、ArrayList 这三个源码。</p>
<p> </p>
<p>恰恰在 AbstractList 已经实现了 List 接口的情况下,其子类 ArrayList  仍然明示的实现了 List 接口。我不知道这是一种严谨的做事风格呢?还是作者出于对自己的充分自信呢(List接口日后肯定不会扩充新方法了!)?</p>
<p> </p>
<p>欢迎大家讨论。</p>
<p> </p>
</div>
<p>1)接口是对象行为的最高抽象,抽象类用来实现多个继承子类共有的逻辑,是否需要抽象类,要看抽象类的继承子类是否具备稳定的共性。你的运输-〉卡车-〉某型号卡车如何建立对象模型和关系要根据“需要”确定,而不是凭空以为要有个抽象类在接口和实类间才合理。甚至某型号卡车有可能是卡车的实例,而不是一个某型号卡车类。</p>
<p>2)当ArrayList需要有新的接口实现方式时,必须采用覆盖来重写AbstractList的方法,这与做事严谨与否无关。</p>
14 楼 lf008 2009-05-16  
应该是public abstract class 卡车运输able implements 交通运输able 才是抽象类吧
13 楼 songze39 2009-05-15  
运输--》卡车运输--》皮卡运输
    
12 楼 iaimstar 2009-05-15  
TonyLian 写道


我也是在看这本书的时候,才想到的这个问题。我的书可能和你的不是一个中译版,第88页与这个无关。
你这个第88页,是《接口优于抽象类》这条吗? 我的书是潘爱民版的。

即便有AbstractList这个抽象类可以在日后扩充List接口是,填补默认实现,但是依旧是在ArrayList中不写实现List也是可以的呀。

我还是不能揣摩Joshua的目的,到底是不是仅仅是一种严谨的做事风格呢?还是有其他用意?


具体是89页,我说88页是这块部分的
这是个是卵还是蛋的问题,我觉得的,作者本身是在强调arrayList实现了List的,骨架类的作用只是方便接口增加,如果去掉实现List,别人阅读起来就不会那么流畅了,这样写,大家很容易明白,arrayList实现了List,所以arrayList可以做什么,List是重点,不是AbstractList,去掉就失去一种明文的说明,变得晦涩了。
11 楼 whaosoft 2009-05-15  
呵呵 我这基础知识不劳的人 就不评论了
10 楼 TonyLian 2009-05-15  
iaimstar 写道
刚才翻了翻,思考的顺序反了就造成这个结果。
这叫个什么模式来着?偶忘了
从作者写ArrayList开始,首先ArrayList实现了List,有很多List实现,如果List要增加接口,所有的实现类就必须都修改,于是作者增加了AbstractList,这样只要实现List接口的类继承了这个AbstractList,即使List接口发生了变化,只需要修改AbstractList就可以保证其他的所有不需要新方法的List实现者继续正常工作,所以作者的思考顺序是ArrayList首先实现了List,然后才去继承了AbstractList

参考阅读
Effective Java中文版的88页

http://forums.sun.com/thread.jspa?threadID=693119&tstart=1844


我也是在看这本书的时候,才想到的这个问题。我的书可能和你的不是一个中译版,第88页与这个无关。
你这个第88页,是《接口优于抽象类》这条吗? 我的书是潘爱民版的。

即便有AbstractList这个抽象类可以在日后扩充List接口是,填补默认实现,但是依旧是在ArrayList中不写实现List也是可以的呀。

我还是不能揣摩Joshua的目的,到底是不是仅仅是一种严谨的做事风格呢?还是有其他用意?
9 楼 hocus 2009-05-15  
8 楼 抛出异常的爱 2009-05-15  
iaimstar 写道
刚才翻了翻,思考的顺序反了就造成这个结果。
这叫个什么模式来着?偶忘了
从作者写ArrayList开始,首先ArrayList实现了List,有很多List实现,如果List要增加接口,所有的实现类就必须都修改,于是作者增加了AbstractList,这样只要实现List接口的类继承了这个AbstractList,即使List接口发生了变化,只需要修改AbstractList就可以保证其他的所有不需要新方法的List实现者继续正常工作,所以作者的思考顺序是ArrayList首先实现了List,然后才去继承了AbstractList

参考阅读
Effective Java中文版的88页

http://forums.sun.com/thread.jspa?threadID=693119&tstart=1844

受教了....这样也可以啊
7 楼 iaimstar 2009-05-15  
刚才翻了翻,思考的顺序反了就造成这个结果。
这叫个什么模式来着?偶忘了
从作者写ArrayList开始,首先ArrayList实现了List,有很多List实现,如果List要增加接口,所有的实现类就必须都修改,于是作者增加了AbstractList,这样只要实现List接口的类继承了这个AbstractList,即使List接口发生了变化,只需要修改AbstractList就可以保证其他的所有不需要新方法的List实现者继续正常工作,所以作者的思考顺序是ArrayList首先实现了List,然后才去继承了AbstractList

参考阅读
Effective Java中文版的88页

http://forums.sun.com/thread.jspa?threadID=693119&tstart=1844
6 楼 iaimstar 2009-05-15  
是不会编译出错,不过既然是Collection的东西,想必Joshua Bloch这个家伙知道点什么,可以翻翻Effective Java ,我怀疑里面肯定有
5 楼 TonyLian 2009-05-15  
iaimstar 写道
强调子类有独立的实现,方便阅读吧

抽象类有了对接口实现,子类没有实现也不会出现编译错误,在接口调用的时候,调用的都是抽象类的实现,如果在子类有了实现,是以覆盖超类方法的形式出现的,明显没有实现接口的约束力强,如果indexOf方法,你写成了indexof,这时不会出现编译错误,调用时候还是会调用超类的方法,子类的独立实现就成了永远不会用到的部分。


即便子类也实现接口,如果把indexOf写成了indexof,也同样不会编译出错呀,依然是使用超类的indexOf。
从这一点上看不出 子类 写不写 implements 接口 的差别吧。
4 楼 抛出异常的爱 2009-05-14  
TonyLian 写道
抛出异常的爱 写道
抽象类的名子叫:卡车运输....不叫卡车.


为什么呢?

是不是应该:
子类叫 卡车,抽象类叫 Abstract交通运输

这样才符合命名习惯

名子清楚了,意义也就明确了
用的时候就不太会用错

不产生歧义是接口的一个重要作用.
3 楼 iaimstar 2009-05-13  
强调子类有独立的实现,方便阅读吧

抽象类有了对接口实现,子类没有实现也不会出现编译错误,在接口调用的时候,调用的都是抽象类的实现,如果在子类有了实现,是以覆盖超类方法的形式出现的,明显没有实现接口的约束力强,如果indexOf方法,你写成了indexof,这时不会出现编译错误,调用时候还是会调用超类的方法,子类的独立实现就成了永远不会用到的部分。
2 楼 TonyLian 2009-05-13  
抛出异常的爱 写道
抽象类的名子叫:卡车运输....不叫卡车.


为什么呢?

是不是应该:
子类叫 卡车,抽象类叫 Abstract交通运输

这样才符合命名习惯
1 楼 抛出异常的爱 2009-05-13  
抽象类的名子叫:卡车运输....不叫卡车.

相关推荐

    常见设计模式的解析和实现(C++)

    在C++中,可以通过抽象工厂类定义一个接口,然后由具体的子类去实现这个接口,创建所需的对象。 2. 单例模式:单例模式确保一个类只有一个实例,并提供全局访问点。在C++中,通常通过私有构造函数和静态成员函数来...

    模板方法模式 实现通用的权限控制

    下面,我们基于上述原理,讨论如何使用模板方法模式实现一个通用的权限控制系统。 ##### 抽象类定义 首先,定义一个抽象基类`CRightBase`,其中包含了所有可能的权限(如添加、编辑、删除等),以及用于执行这些...

    C#设计模式大全

    这个问题用来比喻设计模式中的一个基本问题——是先定义接口还是先实现类。通常建议先定义接口,再实现类,这样可以更好地支持多态性和灵活性。 #### 大瓶子套小瓶子还是小瓶子套大瓶子? 这是对组合模式的一个...

    设计模式的一些实现代码

    在VC6.0中,可以使用接口和实现类来实现策略模式,增加代码的灵活性。 以上就是“设计模式的一些实现代码”中涉及到的主要设计模式。这些模式都是软件设计中的重要工具,通过理解和应用这些模式,开发者可以在解决...

    各种设计模式c#代码

    C#中,可以使用抽象工厂类和具体工厂子类来实现。 - 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在C#中,可以通过接口和继承实现。 - 建造者模式:将复杂对象的构建与其...

    用Java实现的设计模式.zip

    2. 工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 3. 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。 4. ...

    java与模式一书源代码

    4. **集合框架**:Java集合框架是存储和管理对象的核心工具,包括List、Set、Map等接口及其实现类。书中会展示如何使用ArrayList、LinkedList、HashMap等类,以及如何使用泛型来增强类型安全。 5. **多线程**:Java...

    sqlfactory

    这是一种行为设计模式,允许我们在一个抽象类中定义算法的骨架,而将一些步骤延迟到子类中。在SQL操作的场景中,可能有一个抽象的SQL模板类,它包含了执行查询的基本步骤,如建立连接、预编译SQL、绑定参数、执行和...

    java实现的设计模式code

    在Java中,可以使用枚举、双重检查锁定或静态内部类来实现单例。 2. **工厂模式**:提供一个接口来创建对象,但允许子类决定实例化哪一个类。Java中可以使用抽象工厂、简单工厂和工厂方法等实现方式。 3. **建造者...

    23种设计模式(C++)

    - **实现**:定义抽象类和实现类的接口。 2. **Adapter模式** - **定义**:将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 - **用途**:...

    java设计模式代码实现

    2. **工厂方法模式**:定义一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类。 3. **抽象工厂模式**:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。...

    基于Python的设计模式研究.zip

    在Python中,可以通过定义接口类和多个实现类来实现。 - 建造者模式:将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。Python中,可以通过定义构建步骤并逐步组装对象来实现。 2. 结构型...

    zhongjiezhe-shejimoshi-leitu-daima

    2. **实现中间者**:中间者类实现接口,知道如何与其他参与者通信。 3. **参与者类**:每个参与者都有一个对中间者对象的引用,通过这个引用进行通信,而不是直接与其他参与者通信。 4. **参与者的交互**:参与者...

    第4章 复习与讨论1

    `AbstractClass`是模板方法类,`ConcreteClassA`和`ConcreteClassB`是具体实现类。 这些设计模式常常相互结合使用,比如职责链模式与组合模式结合,组合模式与迭代器模式结合,命令模式与备忘录模式结合,以及迭代...

    java设计模式源码和笔记(第一部分)

    2. **工厂模式**:提供一个接口用于创建对象,但让子类决定实例化哪一个类。在Java中,工厂模式分为简单工厂、工厂方法和抽象工厂三种。笔记可能涵盖了如何在Eclipse中创建工厂类和调用过程。 3. **观察者模式**:...

    大话模式源代码 。。。.....

    C#中,策略模式常用于实现行为上的选择,通过接口或抽象类定义策略接口,具体策略类实现这些接口。 10. 组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的...

    C#实现设计模式(23种)

    2. **工厂模式**:定义一个创建对象的接口,让子类决定实例化哪一个类,将对象创建过程延迟到子类中。 3. **抽象工厂模式**:提供一个创建一系列相关或相互依赖对象的接口,无需指定其具体类。 4. **建造者模式**...

    GoF设计整理(C#实现)在示意图、C#代码的基础上,又增加了设计模式意图、使用场景和重构成本,并增加了PDF书签功能。以后还将持续完善。下载.

    - 使用场景:想使用已经存在的类,而它的接口不符合需求时。 - 重构成本:低。 - **Bridge(桥接模式)** - 定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。 - 意图:解耦实现与抽象层。 - 使用...

    C#23种设计模式【完整】__0525.rar

    C#中,可以使用接口和类的多态性实现。 23. **模板方法模式**:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。C#中的虚方法和抽象类可以...

    设计模式_C++语言实现

    `09.pdf`可能讨论了如何在C++中实现策略模式以及如何在运行时动态选择算法。 10. **模板方法模式**(Template Method):在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的...

Global site tag (gtag.js) - Google Analytics