6

これはAndroid固有です。

Androidのすべてのアクティビティは、アプリケーションのすべてのレイアウトで使用される一般的なコード、特にレイアウトをレイアウトに挿入するいくつかの一般的なsetContentView()オーバーライドコードを配置するためのすてきでクリーンな場所を提供するカスタムクラスから派生しています。したがって、典型的な階層は次のようになります。

MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity

私のアプリの1つには、Googleマップのサポートが必要でした。そこで、MyBaseClassをテンプレート/ジェネリックに変換して、次のようなことができるようにしました。

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

もちろん、Javaテンプレート/ジェネリックは、試行直後に発見したC ++テンプレートほど有用ではないため、コンパイルに失敗しました。そのため、一時的な回避策として、まったく別のクラスを作成することになりました。

MyActivity extends MyBaseMapClass -> MyBaseMapClass extends MapActivity -> MapActivity

そして、すべてのコードをMyBaseClassからMyBaseMapClassにコピーしました。インポートに関連するいくつかの小さな変更を除いて、コードは同じです。それは機能しますが、それはほとんど良い解決策ではありません。

私は、上記が問題の終わりであり、二度とそれを再検討する必要がないだろうと指を交差させました。

残念ながら、私ははるかに複雑な基本クラスを使用したフラグメントとアクティビティの組み合わせを実験し始めており、上記のコード重複の問題は深刻な問題になりつつあります。1つのファイルに変更を加えるときはいつでも、それを他のファイルに複製することを忘れないでください。開発は十分に速く進んでいるため、すぐに同期がとれなくなります。

Activity、MapActivity、FragmentActivity、ListActivity、PreferenceActivityなど。使用するクラスごとに個別の派生クラスを作成する必要がありますか?私はそうしないことを望みます、そしてこの理由で、私はすでに私の派生を最初に制限しました(私の活動のいくつかは結果として特定の機能を持っていません)。この問題は、2つの別々の基本クラスを使用することがあるという事実によってさらに悪化します(一部のアクティビティではさらに多くのビューをレイアウトに拡張する必要がありますが、すべてのアクティビティで拡張する必要はありません)。

MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity

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

マップでAnotherBaseClassのコードを使用する場合は、MyBaseMapClassだけでなく、AnotherBaseMapClassも作成してコードをコピーする必要があります。この時点で私は最大4つのクラスになり、そのうちの2つは数千行の複製されたコードです。複製されたコードは、メンテナンスと開発を非常に困難にするため、私を悩ませます。

Androidクラスを派生させると、Activity基本クラスの一部であるfindViewById()などの複雑さが生じます。今説明したのと同じ問題に遭遇することなく、インターフェイスまたはコンポジットをどのように作成するかわからないため、これは重要です。

ここの誰かがこの問題に遭遇し、実行可能な解決策を考え出しますか?

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;

MyMapActivityしたがって、として扱う必要があるときはいつでも、変数MyBaseClassを使用してください。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によって提案されたヘルパークラスに固執します。

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 に答える