Java缺乏模板继承导致Android中的主要代码重复问题。有解决方案吗

时间:2012-10-31 21:04:11

标签: java android multiple-inheritance

这是针对Android的。

我从一个自定义类中获取Android中的所有活动,该类提供了一个漂亮,干净的位置,可以放置应用程序中所有布局使用的公共代码,尤其是一些常见的setContentView()覆盖代码,它将布局注入到我的布局中。所以这是典型的层次结构:

MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity

对于我的某个应用,我需要Google地图支持。所以我试图将MyBaseClass转换为模板/泛型,以便我可以做类似的事情:

MyActivity extends MyBaseClass<MapActivity> -> MyBaseClass<T> extends T -> T

当然,编译失败的原因是Java模板/泛型不像我在尝试后不久发现的C ++模板那么有用。所以我最终创建了一个完整的单独的类作为临时解决方法:

MyActivity extends MyBaseMapClass -> MyBaseMapClass extends MapActivity -> MapActivity

将MyBaseClass中的所有代码复制到MyBaseMapClass中。除了涉及进口的一些小改动之外,代码是相同的。它有效,但它不是一个好的解决方案。

我越过手指,上面的问题将会结束,我再也不会再重访了。

不幸的是,我开始尝试使用更复杂的基类进行片段和活动混合,并且上面的代码重复问题变成了一个严重的问题。每当我在一个文件中进行更改时,我必须记住将其克隆到其他文件,并且开发速度足够快,以至于我很快就会失去同步。

Activity,MapActivity,FragmentActivity,ListActivity,PreferenceActivity等。我是否需要为我想要使用的每一个创建一个单独的派生类?我希望不会,因为这个原因,我已经开始限制我的推导(我的一些活动因此没有某些特征)。我有时会使用两个单独的基类(其中一些活动需要将更多视图扩展到布局中,但并非所有活动都需要这样做),这进一步加剧了这个问题:

MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity

MyActivity2 extends AnotherBaseClass -> AnotherBaseClass extends MyBaseClass -> MyBaseClass extends Activity -> Activity

如果我想在Maps中使用AnotherBaseClass的代码,我不仅需要创建MyBaseMapClass,还需要创建AnotherBaseMapClass并复制代码。此时我最多有四个班级,其中两个班级是几千行克隆代码。复制代码困扰我,因为它使维护和开发变得更加困难。

派生Android类会引入复杂性,例如findViewById()是Activity基类的一部分。这很重要,因为我不确定如何编写接口或复合材料而不会遇到我刚才描述的相同问题。

此处有人遇到此问题并提出可行的解决方案吗?

3 个答案:

答案 0 :(得分:2)

为什么不用styleActivity(Activity a)之类的静态函数创建一个辅助类?在这种情况下,这似乎比使用继承更容易。

答案 1 :(得分:0)

所以基本上你想要多重继承,Java不支持。

可以模拟多重继承

interface MyBaseInterface
    foo();
    bar();

class MyBaseClass implements MyBaseInterface
    foo(){ ... };
    bar(){ ... };

class MyMapActivity extends MapActivity implements MyBaseInterface

    // boiler plate c&p
    MyBaseClass base;
    foo(){ return base.foo(); }
    bar(){ return base.bar(); }

但是,MyMapActivity必须implements MyBaseInterface的原因是什么?可能没有。

也许这已经足够了

class MyBaseClass
    foo(){ ... };
    bar(){ ... };

class MyMapActivity extends MapActivity

    public final MyBaseClass base;

因此,每当您需要将MyMapActivity视为MyBaseClass时,只需使用base变量即可。

    activity.base.foo();

用于抽象/覆盖方法

class MyMapActivity extends MapActivity

    public final MyBaseClass base = new MyBaseClass()
    {
        foo(){ do my foo thing; } 
    }

答案 2 :(得分:0)

事实上,你自己的声明“Java模板/泛型并不像C ++模板那么有用”是你问题的最佳答案:)。

class MyClass<T> extends T这样的构造在java中不幸是非法的。即使它们是合法的,它们也意味着与class MyClass extends Object相同,因为参数化类型在字节码中被删除。 (阅读关于类型擦除http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20erasure?

我会坚持使用SimonSays在另一个答案中建议的助手课程。

class MyHelper<T extends Activity> {

    final T activity;

    public MyHelper(T activity) {
        this.activity = activity;

        //here you can access Acitivities methods on T object 
        //and compiler will not say a single bad word ;)
        //unfotunately only public methods
        activity.getLayoutInflater();
    }

    public T getActivity() {
        return activity;
    }
}