メソッド呼び出しでパラメータタイプの継承を使用するにはどうすればよいですか?

アレックスマッサ

私は学校のプロジェクト用にJavaWebアプリケーションを開発しており、MVCアーキテクチャパターンにできる限り従っています。これを実現するために、JavaBeanクラスのセットを作成し、Gsonを使用してこれらのインスタンスをシリアル化および逆シリアル化します。私が抱えている問題は、Javaで継承とジェネリックがどのように機能するかを完全に理解していないことを示しているので、この質問でそれらの議論に光を当てたいと思います。

私は2つの抽象クラス持つItemItemVariantそれぞれ二つのBeanクラスごと、によって拡張され、CatalogItemArchivedItemCatalogItemVariantArchivedItemVariantのインスタンスはItemのコレクションを参照できItemVariant、その逆も同様です。のインスタンスはItemVariantその親アイテムを参照できます(これによりシリアル化プロセスでループが発生する可能性があることはわかっていますが、これは私が経験している問題ではありません)。したがって、理想的には、のインスタンスはCatalogItem常にコレクションCatalogItemVariant参照し、のインスタンスはCatalogItemVariant常にの1つを参照する必要がCatalogItemあり、同じことがArchivedItemとにも当てはまりますArchivedItemVariantしかし、私はこの関係を強制することに興味がありません。たとえば、のインスタンスがのインスタンスをCatalogItemVariant参照できるようにするArchivedItemことは許可されています。

現在、これら2つの抽象クラスのコードは次のようになっています。

public abstract class Item implements Serializable {
    ...
    protected Collection<ItemVariant> variants;
    ...
    public <T extends ItemVariant> Collection<T> getVariants() {
        return (Collection<T>) variants;
    }
    ...
    public <T extends ItemVariant> void setVariants(Collection<T> variants) {
        this.variants = (Collection<ItemVariant>) variants;
    }

}

public abstract class ItemVariant implements Serializable {
    ...
    protected Item parentItem;
    ...
    public <T extends Item> T getParentItem() {
        return (T) parentItem;
    }
    ...
    public <T extends Item> void setParentItem(T parentItem) {
        this.parentItem = parentItem;
    }
    ...
}

これはチェックされていないキャスト警告を生成しており、おそらく最も洗練された解決策ではないことを私は知っています。しかし、これは私が経験している大きな問題ではありません。

これら2つを拡張するBeanクラスは、ゲッターとセッターとともにそれぞれ2つのプロパティを追加するだけであり、これらの具象クラスのインスタンスは、アプリケーション全体で実際に使用されるものです。ここで本当の問題が発生しますCatalogItemVariant例として、のインスタンスに逆シリアル化する必要がある次のJSON文字列について考えてみます

{"parentItem":{"name":"Sample name","category":"Sample category","color":"Sample color"},"size":"Sample size"}

理想的にparentItemは、のインスタンスに逆シリアル化する必要がありますがCatalogItem、これらのクラスが現在設計されている方法を考えると、Gsonはのインスタンスを作成しようとしますItem。これは抽象的であるため、次の例外が発生します。

java.lang.RuntimeException: Failed to invoke public model.transfer.catalog.Item() with no args

この問題を回避するには、私は2つの方法を作ることを考えsetVariantsItemsetParentItemにおけるItemVariantので、2オーバーライドしてそれらのサブクラスを強制的、抽象的に。このようなもの:

public abstract class ItemVariant implements Serializable {
    ...
    protected Item parentItem;
    ...
    public abstract <T extends Item> void setParentItem(T parentItem);
    ...
}

public class CatalogItemVariant extends ItemVariant {
    ...
    @Override
    public void setParentItem(CatalogItem parentItem) {
        this.parentItem = parentItem;
    }
    ...
}

ただし、タイプCatalogItemが一致せずT@Override注釈が無効になるため、これは機能しません

この回避策は、正しいクラス(使用して2つの異なるオブジェクトにそれらの両方をデシリアライズ、オブジェクト二つの別々のJSON文字列、項目バリアント用とその親項目のための1つをデシリアライズサーブレットに送信されるCatalogItem最初のおよびCatalogItemVariantのための2番目)、次にを使用しparentItemて新しいCatalogItemVariantインスタンスの属性手動で設定しますsetParentItem()もちろん、このソリューションを適用する場合、アイテムバリアントのJSON文字列はそのparentItemフィールドを見逃す必要があります。これに対するより良い解決策はありますか?もしそうなら、この問題の影響を受けるクラスとメソッドをどのように再設計する必要がありますか?

編集:実際のコードを提供するように求められたので、これが私が使用しているクラスの簡略化されたバージョンです:

public abstract class Item implements Serializable {

    private static final long serialVersionUID = -6170402744115745097L;

    protected String name;
    protected String category;
    protected String color;
    protected Collection<ItemVariant> variants;

    public String getName() {
        return this.name;
    }

    public String getCategory() {
        return this.category;
    }

    public String getColor() {
        return this.color;
    }

    public <T extends ItemVariant> Collection<T> getVariants() {
        return (Collection<T>) variants;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public <T extends ItemVariant> void setVariants(Collection<T> variants) {
        this.variants = (Collection<ItemVariant>) variants;
    }

}

public abstract class ItemVariant implements Serializable {

    private static final long serialVersionUID = 4245549003952140725L;

    protected Item parentItem;
    protected String size;

    public <T extends Item> T getParentItem() {
        return (T) parentItem;
    }

    public String getSize() {
        return size;
    }

    public <T extends Item> void setParentItem(T parentItem) {
        this.parentItem = parentItem;
    }

    public void setSize(String size) {
        this.size = size;
    }

}

public class CatalogItem extends Item implements Serializable {

    private static final long serialVersionUID = 993286101083002293L;

    protected String description;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

}

public class CatalogItemVariant extends ItemVariant implements Serializable {

    private static final long serialVersionUID = -2266390484210707778L;

    protected Integer availability;

    public Integer getAvailability() {
        return availability;
    }

    public void setAvailability(Integer availability) {
        this.availability = availability;
    }

}

私が経験したエラーは、次のコードスニペットを実行することでシミュレートでき、最後の行にスローされます。

Gson gson = new GsonBuilder().create();
CatalogItem catalogItem;
CatalogItemVariant catalogItemVariant;
CatalogItemVariant deserializedCatalogItemVariant;

catalogItem = new CatalogItem();
catalogItem.setName("Sample name");
catalogItem.setCategory("Sample category");
catalogItem.setColor("Sample color");

catalogItemVariant = new CatalogItemVariant();
catalogItemVariant.setSize("Sample size");
catalogItemVariant.setParentItem(catalogItem);

String serializedCatalogItemVariant = gson.toJson(catalogItemVariant);  // Builds a JSON string of the object to serialize
System.out.println(serializedCatalogItemVariant);   // Prints the JSON string of the serialized object which is fed for deserialization in the next instruction
deserializedCatalogItemVariant = gson.fromJson(serializedCatalogItemVariant, CatalogItemVariant.class);

明確にするために、これらのクラスの設計方法が原因でエラーが発生することを完全に理解しており、プログラムの動作が異なるとは思わない。ジェネリックスと継承を使用してそれらのクラスを再設計できる方法があるかどうか、もしそうなら、その方法は何かを理解したいだけです。

アレックスマッサ

この質問に遭遇した人は、この非常に単純な解決策を見てください

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Mockitoを使用して列挙型パラメーターでメソッド呼び出しを検証するにはどうすればよいですか?

分類Dev

InvokeCommandActionを使用して私のメソッドを呼び出し、パラメーターを渡すにはどうすればよいですか?

分類Dev

JasperReportsから2つのパラメーターを使用してJavaメソッドを呼び出すにはどうすればよいですか

分類Dev

同じメソッドを複数回呼び出すようにディスパッチし、WPFアプリのパラメーターとして呼び出し順序番号を指定するにはどうすればよいですか?

分類Dev

RabbitMQ Publish and Subscriberパターンを使用しているときに別のメソッドを呼び出すにはどうすればよいですか?

分類Dev

SPELは、どのようにメソッド呼び出しでパラメータを使用するには?

分類Dev

メソッドを呼び出すときにパッケージタイプを変更するにはどうすればよいですか?

分類Dev

このメソッドを呼び出してパラメータを渡すにはどうすればよいですか?

分類Dev

異なるパラメーターで呼び出されるメソッドを取得するにはどうすればよいですか?

分類Dev

継承クラスのメソッド実装を強制して、独自の埋め込みを呼び出す前にベースメソッドを呼び出すにはどうすればよいですか?

分類Dev

フラッターで特定のタブに移動するたびにメソッドinitStateを呼び出すにはどうすればよいですか?

分類Dev

マップ関数の呼び出しでパラメータータプルを解凍するにはどうすればよいですか?

分類Dev

Springで@Validパラメータを使用して@RequestMethodメソッドで実行される同じバリデータをプログラムで呼び出すにはどうすればよいですか?

分類Dev

「実際の」メソッドのモックメソッドの呼び出しでパラメータを使用するにはどうすればよいですか?

分類Dev

1つのパラメータに基づいて昇順でメソッドを呼び出すにはどうすればよいですか?

分類Dev

defaultdictを継承し、そのコピーメソッドをサブクラスメソッドで使用するにはどうすればよいですか?

分類Dev

パラメータなしでメソッドを作成して呼び出すにはどうすればよいですか?

分類Dev

onReceiveメソッド呼び出しのこのSwiftコンパイラエラーを修正するにはどうすればよいですか?

分類Dev

Javascriptでパラメータの関数を$ httpgetメソッドに呼び出すにはどうすればよいですか

分類Dev

C#でメソッド呼び出しをインターセプトするにはどうすればよいですか?

分類Dev

パラメータなしでメソッドを呼び出すにはどうすればよいですか?

分類Dev

Wordメソッドを呼び出してパラメーターを渡すにはどうすればよいですか?

分類Dev

Graphics gをパラメーターとして持つメソッドを呼び出すにはどうすればよいですか?

分類Dev

メソッドパラメータとしてオブジェクトを呼び出すにはどうすればよいですか?

分類Dev

セルフメソッドを呼び出してフラスコ内のデータを取得するにはどうすればよいですか?

分類Dev

パターンマッチングを使用して、Tベースからメソッドを呼び出すにはどうすればよいですか?

分類Dev

Java:再帰呼び出しで元のパラメータを使用してメソッドを再帰的に呼び出すにはどうすればよいですか?

分類Dev

メソッド(複数のメソッド)をパラメーターとして継承されたvoidメソッドまたはC#のデリゲートに渡すにはどうすればよいですか?

分類Dev

salesforce apexクラスでパラメータ化されたメソッドを呼び出すにはどうすればよいですか

Related 関連記事

  1. 1

    Mockitoを使用して列挙型パラメーターでメソッド呼び出しを検証するにはどうすればよいですか?

  2. 2

    InvokeCommandActionを使用して私のメソッドを呼び出し、パラメーターを渡すにはどうすればよいですか?

  3. 3

    JasperReportsから2つのパラメーターを使用してJavaメソッドを呼び出すにはどうすればよいですか

  4. 4

    同じメソッドを複数回呼び出すようにディスパッチし、WPFアプリのパラメーターとして呼び出し順序番号を指定するにはどうすればよいですか?

  5. 5

    RabbitMQ Publish and Subscriberパターンを使用しているときに別のメソッドを呼び出すにはどうすればよいですか?

  6. 6

    SPELは、どのようにメソッド呼び出しでパラメータを使用するには?

  7. 7

    メソッドを呼び出すときにパッケージタイプを変更するにはどうすればよいですか?

  8. 8

    このメソッドを呼び出してパラメータを渡すにはどうすればよいですか?

  9. 9

    異なるパラメーターで呼び出されるメソッドを取得するにはどうすればよいですか?

  10. 10

    継承クラスのメソッド実装を強制して、独自の埋め込みを呼び出す前にベースメソッドを呼び出すにはどうすればよいですか?

  11. 11

    フラッターで特定のタブに移動するたびにメソッドinitStateを呼び出すにはどうすればよいですか?

  12. 12

    マップ関数の呼び出しでパラメータータプルを解凍するにはどうすればよいですか?

  13. 13

    Springで@Validパラメータを使用して@RequestMethodメソッドで実行される同じバリデータをプログラムで呼び出すにはどうすればよいですか?

  14. 14

    「実際の」メソッドのモックメソッドの呼び出しでパラメータを使用するにはどうすればよいですか?

  15. 15

    1つのパラメータに基づいて昇順でメソッドを呼び出すにはどうすればよいですか?

  16. 16

    defaultdictを継承し、そのコピーメソッドをサブクラスメソッドで使用するにはどうすればよいですか?

  17. 17

    パラメータなしでメソッドを作成して呼び出すにはどうすればよいですか?

  18. 18

    onReceiveメソッド呼び出しのこのSwiftコンパイラエラーを修正するにはどうすればよいですか?

  19. 19

    Javascriptでパラメータの関数を$ httpgetメソッドに呼び出すにはどうすればよいですか

  20. 20

    C#でメソッド呼び出しをインターセプトするにはどうすればよいですか?

  21. 21

    パラメータなしでメソッドを呼び出すにはどうすればよいですか?

  22. 22

    Wordメソッドを呼び出してパラメーターを渡すにはどうすればよいですか?

  23. 23

    Graphics gをパラメーターとして持つメソッドを呼び出すにはどうすればよいですか?

  24. 24

    メソッドパラメータとしてオブジェクトを呼び出すにはどうすればよいですか?

  25. 25

    セルフメソッドを呼び出してフラスコ内のデータを取得するにはどうすればよいですか?

  26. 26

    パターンマッチングを使用して、Tベースからメソッドを呼び出すにはどうすればよいですか?

  27. 27

    Java:再帰呼び出しで元のパラメータを使用してメソッドを再帰的に呼び出すにはどうすればよいですか?

  28. 28

    メソッド(複数のメソッド)をパラメーターとして継承されたvoidメソッドまたはC#のデリゲートに渡すにはどうすればよいですか?

  29. 29

    salesforce apexクラスでパラメータ化されたメソッドを呼び出すにはどうすればよいですか

ホットタグ

アーカイブ