0

だから、私はAndroid sqlite用の小さなライブラリを作ろうとしていて、ほとんどの基本的な機能を持っていますが、問題は特定のクラスとして結果を返すことです. 私が持っている

abstract public class Table<RowClass extends Row>{
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = (RowClass) new Row();
    }
}

しかし、row.getClass().getName() をログに記録しようとすると、常に RowClass ではなく Row として返され、RowClass ではなく Row のように動作します。行をRowClassにキャストするにはどうすればよいですか?

編集:テーブルから拡張するもの

public class SourcesTable<Rowclass extends Row> extends Table<Row>
{
    public String getName()
    { return "sources"; }

    public String[] getAllColumns()
    {
        String[] columns = { "name" };
        return columns;
    }
}

そして、私はそれをインスタンス化します

Tables sourcesTable = new SourcesTable<SourcesRow>();
List<SourcesRow> list = sourcesTable.fetchAll();

どこ

public class SourcesRow extends Row
{
    public String toString()
    { return this.data.get("name"); }
}

public class Row
{
    public String toString()
    { return ""; }
}

これが混乱している場合は申し訳ありません。私はPHPからJavaを学んでいるので、これを間違った方法で回避している可能性があります.厳密な型キャストに慣れていないだけです.

4

1 に答える 1

2

これはあなたの関連コードです(あなたが投稿した残りのコードは、実際には不要です:)):

abstract public class Table<RowClass extends Row>{
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = (RowClass) new Row();
    }
}

あなたが求めているのは、 の新しいインスタンスを作成する方法のようですRowClass。できません。Java は、型 RowClass に関する情報を提供しません。型消去のため、ジェネリック パラメーターとして渡された型に関する情報は実行時に存在しません。ジェネリック パラメーターの型のオブジェクトをインスタンス化する場合は、別の方法でクラスを提供する必要があります。例 (明確にするために例外処理を省略):

abstract public class Table<RowClass extends Row>{
    private final Class<RowClass> rowClass; // holds the Class of each row
    public Table (Class<RowClass> rowClass) {
        this.rowClass = rowClass;
    }
    public List<RowClass> fetchAll() {
        //Fetch the stuff here
        //In the while class to add each row to the array
        RowClass row = rowClass.newInstance();
    }
}

次に、Whatever.class を Table コンストラクターに渡します (Table は抽象的であるため、サブクラスは行のクラスをスーパー コンストラクターに渡す必要があります)。

// assume: SpecialRow and MyCustomRow are concrete classes extending Row
// and defined elsewhere.

// scenario 1 - subclass knows row type
public class SpecialTable extends Table<SpecialRow> {
    public SpecialTable () {
        super(SpecialRow.class);
    }
}

// scenario 2 - subclass still lets user specify row type
public class CustomTable <R extends Row> extends Table<R> { 
    public CustomTable (Class<R> rowClass) { 
        super(rowClass);
    }
}

// usage:
SpecialTable special = new SpecialTable();
CustomTable<MyCustomRow> custom = new CustomTable<MyCustomRow>(MyCustomRow.class);

クラスを fetchAll に渡すこともできます。

public List<RowClass> fetchAll(Class<RowClass> rowClass) {
    //Fetch the stuff here
    //In the while class to add each row to the array
    RowClass row = rowClass.newInstance();
}

または、次のようにオブジェクトを渡すこともできます (一般的な toArray() の動作と同様の精神です)。

public List<RowClass> fetchAll(RowClass refObject) {
    //Fetch the stuff here
    //In the while class to add each row to the array
    RowClass row = refObject.getClass().newInstance();
}

詳細については:

編集:あなたがやろうとしていることについての私の推測が正しければ、ここに別の設計アプローチがあります。

Table は抽象的であるため、サブクラスが独自の特定の行タイプを持つ Table サブクラスを作成しようとしているように感じます。その場合、上記の最初のオプション (クラス タイプをスーパー コンストラクターに渡す) が最も適切です。ただし、これをすべて行う代わりに、サブクラスに独自の既知の Row クラスをインスタンス化させ、ベースがそれを実行できるようにする抽象メソッドを提供することを検討することをお勧めします。次に例を示します。

abstract public class Table { // no generics necessary
    // subclasses must override this
    abstract protected Row newRow ();
    // the base class can use newRow() to let the subclass determine the type
    public List<Row> fetchAll () {
        // in the while loop to add each row to the array:
        Row row = newRow();
    }
}

このアプローチには、特定の Row サブクラスを認識している Table サブクラスが、必要に応じて Row サブクラスを構築できるという大きな利点があります。

それが役立つことを願っています。

于 2013-08-06T00:40:21.400 に答える