Java:接口前的受保护方法

3

我需要设计一个数据结构,它将被多次实现,但我遇到了问题。

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

问题变成如下:根据我的数据结构的不同实现,集合需要有不同的实现方法: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个回答

2
不,他们没有“克服这个问题”,因为他们并没有看到任何障碍、问题或限制。根据他们的说法,多重继承在语言中并不是真正需要的,因为至少有85%的情况下它被用于对应组合。剩下14%的情况可以通过接口和非自然使用组合来解决,1%可以通过代码复制来解决。确实:后者很丑陋,冗余和不安全等,但主要目标是创建一个小型语言,即使在嵌入式设备上也可以实现。他们不会为了仅占1%的情况而放弃这一点。在我看来,他们的百分比是正确的。
回答你的第二个问题:尤其是从库类继承时,不要继承,当你真正需要的是组合时。让AbstractEdge拥有一个成员protected Set backingSet;,由子类使用不同的Set实现进行初始化。这意味着你不需要AbstractSetView及其子类。
否则,成员protected Set backingSet;可以位于AbstractSetView中。

0
到目前为止,给出的两个答案都为Set案例提供了解决方案和建议。然而,在这种和其他相似情况下(例如,你不是在扩展一个JRE类,而是你自己的东西),你可以使用一种模式来将接口分为公共接口和内部保护接口。
在这种情况下,你的公共接口将是Set。
你的受保护的内部接口将会是InternalSet,在AbstractEdge内部声明,并定义removeInternal方法。该方法将是“public”,但是该接口不需要是“public”。
接着,抽象超类应该定义一个公共方法,返回子类外部使用的公共接口,还要定义一个保护方法,只为内部使用的受保护接口。
然后,实现子类就可以实现一个类,扩展任何你所需要的Set,并实现受保护的类,并从两个方法中返回它的实例。
选择复合还是继承JRE类之间取决于你自己。

如果您给出反对票,请留下评论,这样也许我们都能学到些东西。 - Simone Gianni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接