在一个类中,我必须调用另一个需要两个参数的类的构造函数,IHelloServiceConnectionObserver
和ContextWrapper
。问题是它们都是this
。
注意:ContextWrapper
是一个我无法控制的框架类(实际上是android.content.ContextWrapper
)。我的班级(Android Activity
)已经是一个ContextWrapper
,我想混合一点IHelloServiceConnectionObserver
。
另请注意,我的班级是从ContextWrapper
继承的几个班级之一,因此合并ContextWrapper
和IHelloServiceConnectionObserer
将无效。
我可以这样做:
HelloServiceConnection svc = HelloServiceConnection(this,this);
呼叫
public HelloServiceConnection(IHelloServiceConnectionObserver observer, ContextWrapper contextWrapper){
this.observer = observer;
this.contextWrapper = contextWrapper;
}
但这看起来很傻。或者我可以这样做:
HelloServiceConnection svc = HelloServiceConnection(this);
呼叫
public HelloServiceConnection(IHelloServiceConnectionObserver observer){
this.observer = observer;
this.contextWrapper = (ContextWrapper) observer;
}
但现在我将一个很好的编译时错误移动到运行时错误。
这里的最佳做法是什么?
编辑:嗯,我不能说这是一个“最佳实践”,但对于我的特殊情况,Jon Skeet有正确的答案。以下是代码最终的结果:helloServiceConnection = HelloServiceConnection.create(this);
呼叫
public static <T extends ContextWrapper & IHelloServiceConnectionObserver> HelloServiceConnection create(T value){
return new HelloServiceConnection(value, value);
}
反过来调用
private HelloServiceConnection(IHelloServiceConnectionObserver observer, ContextWrapper contextWrapper){
this.observer = observer;
this.contextWrapper = contextWrapper;
}
因此,让我更多地说明为什么这是这种特殊情况的正确答案。由于ContextWrapper
是我无法控制的框架的一部分,我无法改变它。因为它也是几个类的祖先,我可能想要使用HelloServiceConnection
中的任何一个,所以将ContextWrapper
的所有后代扩展为IHelloServiceConnectionObserver
并没有多大意义。 }。
所以我认为我只剩下this,this
idom。一旦我理解了乔恩的回答,就可以节省一天的时间!
谢谢,乔恩 - 并感谢所有参与的人。
答案 0 :(得分:5)
嗯,你可以使通话成为通用的:
public <T extends ContextWrapper & IHelloServiceConnectionObserver> void method
(T item)
让类型推断对其进行排序。但这并不是非常令人愉快。
编辑:看起来你正在尝试使用构造函数,这将使其变得更难。您可以使用静态方法创建实例:
public static <T extends ContextWrapper & IHelloServiceConnectionObserver>
HelloServiceConnection createConnection(T value)
{
return new HelloServiceConnection(value, value);
}
private HelloServiceConnection(ContextWrapper wrapper,
IHelloServiceConnectionObserver observer)
{
this.wrapper = wrapper;
this.observer = observer;
}
好的,所以构造函数和类型本身最终会有两个单独的字段 - 但我们知道它们都会引用同一个对象。如果你愿意,你甚至可以在构造函数中断言。
正如其他人所说的那样,值得考虑的是你是否真的需要这种耦合。如果包装器和观察者不是同一个对象会发生什么坏事?
答案 1 :(得分:1)
如果你想指出对象具有ContextWrapper类型并且实现接口的事实,那么你可以在方法调用中强制转换它吗?
method((ContextWrapper)this, (IHelloServiceConnectionHelper)this)
演员阵容显然是多余的,但它使你的观点更明确。
答案 2 :(得分:1)
我认为您应该坚持使用当前的设计,或者ContextWrapper
延长IHelloServiceConnectionObserver
。你将两者合并的论点是new HelloServiceConnection(this, this)
看起来很尴尬。但为什么这种情况会出现呢?
这是因为你碰巧有一个ContextWrapper
和IHelloServiceConnectionObserver
的对象。如果它们应该总是在一起(你通过将两个构造函数参数合并在一起而强迫程序员),那么使一个类型扩展另一个。或者,让HelloServiceConnection
获取一个类型为this
的参数。
如果它们应该分开,那么您当前的代码就可以了。或者,不是让当前的类(this
的类型)扩展/实现ContextWrapper
和IHelloServiceConnectionObserver
,而是可以让它只扩展/实现其中一个并具有成员变量指向另一个的实例。请记住,如有疑问,use composition over inheritance。
答案 3 :(得分:0)
我不会害怕写这段代码:
IHelloServiceConnectionObserver observer = this;
ContextWrapper contextWrapper = this;
HelloServiceConnection svc = new HelloServiceConnection(observer, contextWrapper);
但事实上,我会重新考虑让this
的课程同时为IHelloServiceConnectionObserver
和 a ContextWrapper
。
只要有可能,我的课程要么只扩展1个类,要么只实现1个接口。我喜欢这种方法所提供的清晰度和分离度。这种哲学更喜欢“有一个”关系而不是“一个”关系。 Java中的内部成员类使“每个类的一个继承”方法相当实用。
答案 4 :(得分:0)
理想情况下,您这样做:
HelloServiceConnection svc = HelloServiceConnection((的 IHelloServiceConnectionObserver 强>)此,(的 ContextWrapper 强>)此);
与之前尝试的相同,但更详细!
答案 5 :(得分:0)
另一个(不愉快的IMO)解决方案是创建一个扩展Combined
和IHelloServiceConnectionObserver
接口的接口ContextWrapper
,更改this
的类以实现{{ 1}},并更改ICombined
以获取HelloServiceConnection
类型的单个参数。
答案 6 :(得分:0)
这有用吗?
从概念上讲,它声明了一个泛型类型Combined
,它使用自己作为观察者和上下文包装器来创建HelloServiceConnection
个对象。
class ContextWrapper {}
interface IHelloServiceConnectionObserver {}
class HelloServiceConnection
{
HelloServiceConnection(ContextWrapper cw, IHelloServiceConnectionObserver o)
{
System.out.println("HelloServiceConnection(" + cw + " ," + o + ")");
}
}
abstract class Combined<T> extends ContextWrapper
implements IHelloServiceConnectionObserver
{
public HelloServiceConnection svc()
{
return new HelloServiceConnection(this, this);
}
}
class MyClass extends Combined<MyClass>
{
public static void main(String args[])
{
MyClass mc = new MyClass();
System.out.println(mc);
mc.svc();
}
}