Java:接口前的受保护方法

时间:2013-08-29 23:47:49

标签: java inheritance interface abstract protected

我必须设计一个可以多次实现的数据结构,并且我遇到了一个问题。

由于我的数据结构需要有多个版本,因此我创建了一个抽象类,为所有实现奠定了基础。但是,数据结构也需要某些部件的集合视图。

问题变现如下:根据我的数据结构的实现,集合需要具有不同的实现:HashSet或Collections.SingletonSet。然后,当从集合中添加或删除项目时,这两个实现数据结构将扩展其中的一些以执行其他任务。但是,抽象数据结构还需要一种方法来从内部删除此集合中的元素,以便不执行此额外工作。为此,我想在集合中添加一个受保护的方法,但我不能!

为了说明,这里有一些与我正在创建的数据结构类型相关的示例代码:

public abstract class AbstractEdge {
    public abstract AbstractSetView destination(); //Gives a subclass of AbstractSetView in implementations.

    public void doStuff() {
        destination().removeInternal(foo);
    }

    public abstract class AbstractSetView implements Set<Vertex> {
        protected abstract void removeInternal(Vertex vert);
    }
}

public class Edge extends AbstractEdge {
    public SetView destination() {
        return new SetView();
    }

    public class SetView extends AbstractSetView,Collections.SingletonSet<Vertex> { //Doesn't work this way.
        protected void removeInternal(Vertex vert) {
            //Do stuff.
        }
    }
}

public class HyperEdge extends AbstractEdge {
    public SetView destination() {
        return new SetView();
    }

    public class SetView extends AbstractSetView,HashSet<Vertex> { //Doesn't work this way.
        protected void removeInternal(Vertex vert) {
            //Do stuff.
        }
    }
}

这些是我考虑过的选项:

  • 如上所述,不允许从多个类扩展。
  • 使AbstractSetView成为一个接口会导致removeInternal()方法变为公共,这是不可取的。
  • 使SetView仅扩展AbstractSetView并自己实现一切......两次。但这要求我基本上包含HashSet和SingletonSet实现,作为一个内部类,这是非常难看的。

当然,Java的设计者在这方面取得了一些进展,使我能够使用他们的内置Set实现?我在俯瞰什么?

2 个答案:

答案 0 :(得分:2)

不,他们没有“绕过这个”,因为他们没有看到任何障碍,问题或限制。根据他们的说法,语言中并不真正需要多重继承,因为至少有85%的时间用于真正对应的是组合。其余14%的案例可以通过接口和非自然使用组合来解决,1%可以通过代码复制来解决。是的:后者是U.G.L.Y.和R.E.D.U.N.D.A.N.T.和U.N.S.A.F.E.等,但主要目标是创建一种即使在嵌入式设备中也可以实现的小语言。他们不会仅仅因为1%的案例而放弃这一点。恕我直言,他们的百分比是正确的。

回答你的第二个问题:不继承,特别是来自库类,当你真正需要的是组合时。 Make AbstractEdge有一个成员protected Set backingSet;,它由子类用不同的Set实现初始化。这意味着您不需要AbstractSetView及其子类。

否则,成员protected Set backingSet;可以位于AbstractSetView

答案 1 :(得分:0)

到目前为止给出的两个答案都为Set案例提供了解决方案和建议。但是,您可以在此类和其他类似情况下使用的模式(例如,您没有扩展JRE类,但是您自己的东西)是将接口拆分为公共接口和内部受保护接口。

在这种情况下,您的公共界面将设置为

受保护的内部接口将是在AbstractEdge中声明的InternalSet,用于定义removeInternal方法。该方法将是“公共的”,但界面不需要。

然后,抽象超类应该定义一个返回公共接口的公共方法,以便在子类之外使用,一个受保护的方法返回受保护的接口,仅供内部使用。

然后,实现子类可以实现一个类,扩展您需要的任何Set,并实现受保护的类,并从两个方法返回它的实例。

组合之间的选择或从JRE类继承都是你的。