传递给Java中的方法时,如何要求参数为两种类型

时间:2011-02-25 06:23:30

标签: java

在一个类中,我必须调用另一个需要两个参数的类的构造函数,IHelloServiceConnectionObserverContextWrapper。问题是它们都是this

注意:ContextWrapper是一个我无法控制的框架类(实际上是android.content.ContextWrapper)。我的班级(Android Activity)已经是一个ContextWrapper,我想混合一点IHelloServiceConnectionObserver

另请注意,我的班级是从ContextWrapper继承的几个班级之一,因此合并ContextWrapperIHelloServiceConnectionObserer将无效。

我可以这样做:

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。一旦我理解了乔恩的回答,就可以节省一天的时间!

谢谢,乔恩 - 并感谢所有参与的人。

7 个答案:

答案 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)看起来很尴尬。但为什么这种情况会出现呢?

这是因为你碰巧有一个ContextWrapperIHelloServiceConnectionObserver的对象。如果它们应该总是在一起(你通过将两个构造函数参数合并在一起而强迫程序员),那么使一个类型扩展另一个。或者,让HelloServiceConnection获取一个类型为this的参数。

如果它们应该分开,那么您当前的代码就可以了。或者,不是让当前的类(this的类型)扩展/实现ContextWrapperIHelloServiceConnectionObserver,而是可以让它只扩展/实现其中一个并具有成员变量指向另一个的实例。请记住,如有疑问,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)解决方案是创建一个扩展CombinedIHelloServiceConnectionObserver接口的接口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();
    }
}