Cocoa代理的Java等价物是什么?
(我知道我可以将一个接口传递给一个类,并让该类调用适当的方法,但我想知道是否还有其他方法可以实现更接近Cocoa / Objective-C的非正式协议)
答案 0 :(得分:8)
简短的回答是Java中没有任何内容可以像你想的那样接近,但也有其他选择。委托模式并不难实现,它只是不如使用Objective-C那样方便。
“非正式协议”在Objective-C中工作的原因是因为该语言支持类别,它允许您在不对子类进行子类化的情况下向现有类添加方法,甚至可以访问源代码。因此,大多数非正式协议都是NSObject上的一个类别。这在Java中显然是不可能的。
Objective-C 2.0选择了@optional协议方法,这是一种更清晰的抽象方法,也是新代码的首选方法,但在Java中具有相同的优势。
老实说,最灵活的方法是定义委托协议,然后让类实现所有方法。 (使用像Eclipse这样的现代IDE,这很简单。)许多Java接口都有一个附带的适配器类,这是一种不需要用户实现大量空方法的常用方法,但它限制了继承,这使得代码设计不灵活。 (Josh Bloch在他的书“Effective Java”中解决了这个问题。)我的建议是首先只提供一个接口,然后在真正需要的时候添加一个适配器。
无论你做什么,都要避免为“未实现”方法抛出UnsupportedOperationException
。这会强制委托类处理应该是可选方法的异常。正确的方法是实现一个不执行任何操作,返回默认值等的方法。对于没有void返回类型的方法,应该很好地记录这些值。
答案 1 :(得分:5)
我能想到的非正式协议的最佳模拟是一个接口,它还有一个适配器类,允许实现者避免实现每个方法。
public class MyClass {
private MyClassDelegate delegate;
public MyClass () {
}
// do interesting stuff
void setDelegate(MyClassDelegate delegate) {
this.delegate = delegate;
}
interface MyClassDelegate {
void aboutToDoSomethingAwesome();
void didSomethingAwesome();
}
class MyClassDelegateAdapter implements MyClassDelegate {
@Override
public void aboutToDoSomethingAwesome() {
/* do nothing */
}
@Override
public void didSomethingAwesome() {
/* do nothing */
}
}
}
然后有人可以来实现他们关心的东西:
class AwesomeDelegate extends MyClassDelegateAdapter {
@Override
public void didSomethingAwesome() {
System.out.println("Yeah!");
}
}
或者是纯粹的反射,称为“已知”方法。但那太疯狂了。
答案 2 :(得分:2)
没有什么可以阻止你在Java对象中使用委托模式(它只是JDK中常用的模式,就像在Cocoa中一样)。只需要一个符合delegate
接口类型的WhateverDelegate
ivar,然后在您想要委派的实例方法中,将方法调用转发到委托对象(如果存在)。你可能会得到一些看起来很像this的东西,除了Java而不是Obj-C。
就可选接口而言,这将更加困难。我建议声明接口,声明一个将可选方法实现为空方法的抽象类,然后继承抽象类,覆盖您希望此特定对象实现的可选方法。由于Java中缺少多重继承,这里存在一个潜在的严重限制,但这与我能想到的一样接近。