【问题标题】:How can I provided two interfaces (a "public" and and "extended" one) at the same time?如何同时提供两个接口(一个“公共”和“扩展”一个)?
【发布时间】:2013-01-17 14:43:38
【问题描述】:

我有块使用函数step() 执行计算。块可以连接到 彼此与connect(Block)

interface Block {
    void connect(Block b);
    void step();
}

但是,在具体的块实现中(例如在step 中)它应该是 可以从连接块read

class ABlockImpl implements Block {
    private Block src; // link to the block this block is connected to
    public void connect(Block b) {
        src = b;
    }

    public void step() {
        double x = src.read(); // XXX src is of type Block and there is no read() in Block
        /* ... */
    }

    public double read() {
        return 3.14;
    }
}

由于Block 中没有read(),因此无法编译。对于客户来说,“公共”块接口就足够了,我只需要在内部使用read。我可以将read 添加到 Block 界面,但对我来说这感觉不对。

由于 Block 有多种不同的实现,我不能在调用 read 之前将 src 转换为 ABlockImpl

是否有“隐藏”read 的替代方法?

【问题讨论】:

  • 请改写标题和问题,它具有误导性,我必须阅读 3 遍才能明白你的意思。
  • 你有什么建议吗,我想的主要是如何措辞。
  • 听起来你只是想让一个类实现两个不同的接口,但我认为你想要一个不公开的接口,对吗?
  • 我不确定。我想我想要一个没有read 的公共接口,以及一种让块之间保持read 的方式。
  • 我不认为您可以或不想使用界面来执行此操作。客户端可以提供自己的 Block 实现,因此 read() 必须是接口的一部分。听起来好像您想自己提供所有实现。因此,我建议您发布一个带有私有 read() 或其他内容的抽象类。

标签: java oop


【解决方案1】:

你可以有一个公共接口和一个包本地接口

public interface MyPublicInterface {

}

interface MyDirectInterface extends MyPublicInterface {

}

class MyImpl implements MyDirectInterface {

    public void add(MyPublicInterface mpi) {
         MyDirectInterface mdi = (MyDirectInterface) mpi;
         // use mdi
    }

}

【讨论】:

  • 当我将src 的类型更改为MyDirectInterface 时,我不能再在connect(Block) 中分配src,因为调用者给了我一个公共接口实例。
  • 假设所有公共接口的实现都实现了私有接口,您必须将公共接口转换为私有接口。我添加了一个示例。
  • 这种情况下我宁愿在界面上加read,你同意吗?
  • 如果相信开发人员会阅读它,您可以记录该方法供内部使用。你可以给它起一个令人惊讶的名字,比如 $readread$
  • @PeterLawrey 是的,但是如果类 needs 公开,您的解决方案将不再有效。我的意思是,它比我目前想出的要好,但我认为应该指出这一点。
【解决方案2】:

您可以在interface 和块的具体实现之间创建abstract 层并将其命名,例如BlockAdapter

即:

interface Block {
    void connect(Block b);
    void step();
    double read();
}

...

public abstract class BlockAdapter implements Block { 
    double read() {
          return -1; // ? something like that
    }
}

...

public class ABlockImpl extends BlockAdapter { ... }

【讨论】:

  • 我认为这个想法是在界面中没有read()
  • @JohannesSchad 我认为,该作者可能不想要它,因为在通常情况下,他必须将此方法实现添加到所有子类中。 Adapter 模式允许仅在一层中执行此操作,并仅在所需的子类中覆盖此方法。
  • 不,我不想在界面中出现read(如果可能的话)。
  • 为什么不把read从接口中去掉,而是在抽象类中定义protected呢?
  • 我定义的不是protected,而是package local。确实,定义它protected 可能会更好。我这样做是因为问题的作者说:我只在内部需要read
【解决方案3】:

我不认为有一个解决方案可以为您提供您想要的东西,但可能是接近它的东西:

interface Block {
    void connect(Block b);
    void step();
}
interface ReadableBlock extends Block {
    double read();
}

方法read()仍然需要公开,但是可以让外部代码只通过Block接口引用实现,而实现本身来自ReadableBlock

public cass ABlockImpl implements ReadableBlock {
    ....
}
Block b = new ABlockImpl();

【讨论】:

  • 我认为这与 Peter Lawrey 的解决方案非常接近。
  • 除了我的界面具有相同的可见性并且他没有指定界面包含的内容。但我不得不承认,我只是略读了他的回答;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 2022-10-05
  • 2012-01-06
  • 1970-01-01
相关资源
最近更新 更多