public class Bar {
// Third party class -- I don't want to rely on its current interface.
}
public class Foo {
private /* not final */ Bar bar;
public refreshBar() {
bar = new Bar(); // Old references are now "dead".
}
/** Question: The reference this method returns can change. */
public Bar getBar() {
return bar;
}
}
Foo foo = new Foo();
foo.getBar().doThing(); // OK.
Bar bar = foo.getBar(); // BAD - I want this to be forbidden.
bar.doThing(); // ERROR.
如何在编译时进行BAD
换行?如果不能这样做,那我怎么能让它抛出异常呢?它甚至可以受到影响吗?
答案 0 :(得分:3)
简单。 不要公开Bar
并公开您想要的任何方法:
public class Foo {
private Bar bar;
public refreshBar() {
bar = new Bar();
}
public void doOneThing() {
bar.firstThing();
}
public void doAnotherThing() {
bar.secondThing();
}
}
答案 1 :(得分:1)
简短而令人沮丧的答案是:完全没有。这根本不可能。有实现所需行为的方法,但只有在为此应用程序模式设置设计的类时。事后看来,对于#34;遗留代码",可能并不那么容易。
评论中已经提到了一个明显的解决方案:不要通过Bar
公开getBar
。你可以代替提供所有公共方法
public class Foo {
private /* not final */ Bar bar;
//public Bar getBar() { return bar; } // NOPE
public void doThis() { bar.doThis(); }
public void doThat() { bar.doThat(); }
}
但是我会不推荐这个,原因很明显:你评论了Bar
类有一个
// Big mess of public methods.
你确实不想要用所有这些方法污染你的Foo
课程。
编辑:后来更改了评论,而是说Bar
是第三方类,其中有一个提问者不想依赖的界面。这里概述的解决方案可以应用,但在这种情况下,也可以作为缓冲 - 在某种程度上 - 甚至可以帮助防止不兼容的变化
我可以想象另一种方法,可能有点清洁:
从Bar
中提取接口,其中包含您需要的所有公共方法。这通常可以通过IDE(例如Eclipse:" Extract interface")来实现。我们称之为BarInterface
。
从BarInterface
班级返回Foo
的实例:
public BarInterface getBar() { ... }
不要返回bar
,而是返回bar
的包装。基本上,BarInterface
的实现只是委托给Bar
实例。这基本上是一个适配器模式。
interface BarInterface {
public void doThis();
public void doThat();
}
public class Bar
public void doThis() { ... }
public void doThat() { ... }
}
class BarWrapper implements BarInterface {
private Bar delegate;
void setDelegate(Bar delegate) { this.delegate = delegate; }
@Override public void doThis() { delegate.doThis(); }
@Override public void doThat() { delegate.doThat(); }
}
public class Foo {
private /* not final */ Bar bar;
// This can be final!
private final BarWrapper barWrapper = new BarWrapper();
public refreshBar() {
bar = new Bar(); // Old references are now "dead".
barWrapper.setDelegate(bar);
}
// The reference returned here will never change!
public BarInterface getBar() {
return barWrapper;
}
}
当然,这需要付出一些努力(特别是当Bar
类中有很多方法时)。但它可能允许您解决原始问题:人们仍然可以获取他们心爱的Bar(Interface)
- 引用并存储它。对refreshBar()
的任何调用都将导致这些引用透明地更新。
但当然,您必须确定它在您的确切应用案例中是否真的适用或有益。
答案 2 :(得分:0)
以下是为您的目的演示一个简单的包装器:
public class BarWrapper {
public static void doThing() {
foo.getBar.doThing();
}
}
public static void Main( String[] Args) {
foo.getBar // ERROR: does not import FOO
BarWrapper.doThing(); // WORKS
}
答案 3 :(得分:0)
如果Bar
是一个接口,您可以为该接口创建一个Proxy
对象并将其返回。然后,当调用该代理接口上的任何方法时,您可以获取当前的Bar
对象,并将该调用传递给该实例。
请参阅:Proxy文档。