扩展类并实现接口的通用类

67
为了减少类的依赖性,我想通过向继承某个类和实现接口的构造函数传递参数(使用泛型类)来实现。例如:
public interface SomeInterface{
    public void someMethod();
}

public class MyFragment extends Fragment implements SomeInterface{
    //implementation
}

//here is classs, that I need to create. T must extend Fragment and implements 
//SomeInterface. But, I'm afraid, if I'll use MyFragment directly, it will create a
//dependence of SomeClass from MyFragment.

public class SomeClass /*generic?*/ {
    public SomeClass(T parent);
}

这有可能实现吗?

此外,使用我的T类,我想要创建视图,使用T.getActivity()作为上下文。


你能提供更多信息吗?使用Java反射,您可以将一个Class对象传递到方法中,并通过getInterfaces()检查其实现的接口,以及获取/调用Constructor来创建新实例。但是您的具体用例不清楚,因此很难弄清楚如何将这些项目组合在一起来解决您的特定问题。 - devunwired
5个回答

155

如果要实现这种情况,您可以将SomeClass声明为以下内容:

T必须扩展Fragment并实现SomeInterface接口。

public class SomeClass<T extends Fragment & SomeInterface>

这将需要一个类型为T的对象既扩展了Fragment又实现了SomeInterface

此外,使用我的T类,我想要创建视图,使用T.getActivity()作为上下文。

我对Android不熟悉,但如果getActivity()是在Fragment中声明的公共实例方法,那么完全可以在T的实例上调用它,因为编译器将知道所有T必须继承该方法。


你如何使用Mockito创建一个类型为T的模拟类? - B W
1
@bwicks 很好的问题。我猜测你的测试类可能需要声明一个类型,比如 abstract class TestFragment extends Fragment implements SomeInterface,然后用 TestFragment.class 来模拟这个类型。 - Paul Bellora
这太不直观了,谢谢。^^' - Panossa

6

您想做类似这样的事情吗?

class SomeClass {}

interface SomeInterface{
    public void someMethod();
}

class AGenericClass<T> extends SomeClass implements SomeInterface {
    public void someMethod() {}
}

这是允许的。

但你的问题与Android有什么特殊关系吗?我觉得我可能漏掉了一些东西,所以你能提供更多细节吗?

下面更新

我仍然不确定你想做什么,也不确定你需要立即担心依赖关系,但这也是合法的,使用有界类型参数

interface SomeInterface{
    public void someMethod();
}

class Fragment {
    public void aMethodInFragment() { }
}

public class SomeClass <T extends Fragment & SomeInterface> {
    public SomeClass(T parent) {
        parent.someMethod();
        parent.aMethodInFragment();
    }
}

类型参数<T extends Fragment & SomeInterface>指定T应该是Fragment的子类并实现SomeInterface


4

如果我理解您的意思正确的话,您需要一个扩展Fragment并实现某个接口的T类型。因此,您需要编写类似以下代码:

abstract class TemplateFragment extends Fragment implements SomeInterface{}

然后在你的类中

class SomeClass<T extends TemplateFragment> {
...
}

它将完成任务。

它可以工作,但如果您的子类需要实现不同类型的“Fragment”,例如当我们想在此处使用View而不是Fragment时,则无法正常工作。因此,子类可以是CustomView扩展LinearLayout实现SomeInterface由于LinearLayout是View,因此在使用BaseClass <T extends View&SomeInterface>时仍然满足条件。 - Koen

1
对于Kotlin,你可以使用以下语法:

class MyClass<T> where T: AnotherClass, T: SomeInterface

0

在 Kotlin 中的等效写法是:

class SomeClass<T>() where T: Fragment, T: SomeInterface

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接