1

申し訳ありませんが、私の問題をより核心的に、またはより抽象的に説明することはできません。私の問題を説明する最良の方法は、この非常に具体的な例を使用することだと思います。

関数の呼び出し方法に基づいて、文字列を解析し、特定のタイプの特定のコレクションを提供する関数'readCollection'を定義したいと思います。

たとえば、私はそれをそのように使用したいと思います:

ArrayList<Foo> fb = readCollection("Foo1\n Foo2\n Foo3\n");

また

LinkedList<Bar> fb = readCollection("Bar1\n Bar2\n Bar3\n");

もちろん、1つのインスタンス( "Bar ..")を読み取るための'read'メソッドを持つすべてのクラスのインターフェイスを定義しました。

私はいくつかの問題の間に挟まれています:

-当然、関数readCollectionは静的関数である必要がありますが、インターフェイスに静的メソッドを含めることはできません。

-メソッドreadCollectionは、FooやBarなどのタイプの新しいオブジェクトを返す必要がありますが、readCollectionを定義したクラスで一般的に定義されているタイプをインスタンス化できません。

-メソッドが静的に定義されていない場合、そのタイプの特定のオブジェクトを参照せずにメソッドを呼び出すことはできません。これは、前のポイントのために行うことはできません。

FooやBarなどごとにコピーせずにメソッドを作成するにはどうすればよいですか?

私は自分で解決策を見つけたようですが、それは非常に醜くて厄介です。

私は今持っています

public interface Readable<T> {
    public T read(String str); }

public class ReadCollection<T extends Readable<T>> {
    public Collection<T> read(File file, Collection<T> ts, T t) {
        ...
        ts.add(t.read(strLine));
        ...
        return ts; 
} }

public class Bars extends ReadCollection<Bar>{
    ...
    public static void main(String[] args) {
    new Bars().read(new File("fake/path"), new ArrayList<Bar>(), new Bar()); }

ここでは、メソッド'read'を参照するために、結果をBarに返すために、ArrayListの新しいインスタンスを送信しました。どうすればそれを回避できたのかわかりません。

もっと良い方法があると教えてください。どこかで私は後知恵で非常に愚かであると感じたいです。

4

3 に答える 3

2

オブジェクト自体から解析/構築を分割することを考えてください。多くの場合、この2つは非常に別個の関心事です。

あなたは正しい方向に進んでいますが、私はお勧めします:

  1. Readable要素タイプをインターフェースから継承させないでください
  2. Readableインターフェイスの名前を次のように変更しますReader
  3. Reader解析するタイプごとにを 実装します。
  4. ReadCollection.readメソッドのシグネチャを更新して、Reader代わりにT

次に、次のようになります。

public class ReadCollection<T,C extends Collection<T>> {
    public C read(File file, C ts, Reader<T> reader) {
        ...
        ts.add(reader.read(strLine));
        ...
        return ts; 
    } 
}

これにより、リストしたすべての問題を解決する必要がある関心の分離が得られます。

于 2013-01-09T22:58:58.203 に答える
1

APIはインターフェースを介して定義する必要があります。

共有実装は、抽象基本クラスを介して行う必要があります。

では、インターフェイスの利点を失うことなく、抽象基本クラスをどのように使用しますか?

簡単!抽象基本クラスにインターフェースを実装させるだけです。

次に、共有機能を必要とするクラスは抽象基本クラスを拡張できますが、特定の実装に縛られることはありません。これは、たとえば単体テストの作成に便利です。

于 2013-01-09T22:53:59.913 に答える
0

あなたのコメント(@stevevls)と友人の助けを借りて、私が自分で最終的で最良の答えを見つけたことをあなたに伝えることができてうれしいです。

私は今持っています

public interface Reader {
    public Reader read(String str); }

だから私は一般的な議論を削除しました、shichは不必要でした

public class ReadCollection { // no generic class!
public static <R extends Reader, C extends Collection<R>> // generic static function! 
        C readColl(File file, Class<? extends C> collClass, Class<? extends R> readClass) {
    C ts = collClass.newInstance()
        Reader t = readClass.newInstance()
        ...
        ts.add(readClass.cast(t.read(strLine)));
        ...
        return ts; 
} }

そして今、私はどこからでも関数を呼び出すことができます:

ArrayList<Point> l = ReadCollection.readColl(new File("examples/ex1.csv"), ArrayList.class, Point.class);

(PointがReaderを実装している/読み取りメソッドを持っていると仮定します...)

新しいインスタンスを送信せずに、そして重要なことに、クラスReadCollectionをどこにでも拡張する必要がありません。

readメソッドが静的にできないという問題は、インターフェイスReaderで定義されているため、持続します。これが、readClass.newInstance()などを使用する理由です。

それでも、この解決策はもうそれほど醜いものではないと思います。

これが良い解決策であることに同意しますか?

于 2013-01-10T13:12:01.807 に答える