【问题标题】:Java: Protected Method Before InterfaceJava:接口前的受保护方法
【发布时间】:2013-09-02 13:58:20
【问题描述】:

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

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

问题变成如下:集合需要有不同的实现,具体取决于我的数据结构的实现: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 实现?我忽略了什么?

【问题讨论】:

    标签: java inheritance interface abstract protected


    【解决方案1】:

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

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

    否则,成员protected Set backingSet;可以定位到@​​987654326@。

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      选择组合还是从 JRE 类继承由您决定。

      【讨论】:

      • 如果您投反对票,请发表评论,这样也许双方都可以学到一些东西。
      猜你喜欢
      • 2013-04-07
      • 2016-07-25
      • 2011-07-19
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 2011-08-04
      相关资源
      最近更新 更多