6

这是特定于 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 基类的一部分。这很重要,因为我不确定如何编写接口或组合而不遇到我刚才描述的相同问题。

这里有人遇到过这个问题并提出了可行的解决方案吗?

4

3 回答 3

2

你为什么不直接创建一个带有静态函数的辅助类styleActivity(Activity a)呢?在这种情况下,这似乎是比使用继承更容易的解决方案。

于 2012-10-31T22:11:51.247 回答
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;

所以每次你需要对待MyMapActivityasMyBaseClass时,只需使用base变量。

    activity.base.foo();

用于抽象/重写方法

class MyMapActivity extends MapActivity

    public final MyBaseClass base = new MyBaseClass()
    {
        foo(){ do my foo thing; } 
    }
于 2012-10-31T22:35:27.497 回答
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 在另一个答案中建议的 Helper 类。

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;
    }
}
于 2012-10-31T23:15:54.210 回答