0

「自動的に」属性をキャストする際に問題があります。

public abstract class MyType<T> {
    public abstract T getValue(String content);
}

public class MyString extends MyType<String> {
    @Override
    public String getValue(String content) {
        return String.valueOf(content);
    }
}

public class MyInteger extends MyType<Integer> {
    @Override
    public Integer getValue(String content) {
        return Integer.valueOf(content);
    }
}

public class User {
    private String _name;
    private int _id;

    public void setName(String name) {
        _name = name;
    }

    public String getName() {
        return _name;
    }

    public void setId(int id) {
        _id = id;
    }

    public int getId() {
        return _id;
    }
}

public class MainTest {
    public static void main(String[] args) {
        ArrayList<MyType> myTypes = new ArrayList<MyType>();
        myTypes.add(new MyString());
        myTypes.add(new MyInteger());

        User user = new User();

        for (MyType myType : myTypes) {
            try {
                user.setName((String) myType.getValue("foobar")); // getValue always returns an Object that I have to parse
                user.setId((Integer) myType.getValue("42")); // getValue always returns an Object that I have to parse
            } catch (Exception e) {
            }
        }
    }
}

これは私の問題の抽象的な例にすぎないことに注意してください。

鋳物を交換するにはどうすればよいですか?私はこのようなものが必要です:

user.setName((user.getName().getClass()) myType.getValue("foobar"));

残念ながら、日食はこれが間違っていることを教えてくれますThe method getValue(String) is undefined for the type Class<capture#3-of ? extends String>

私は明示的にキャストしません。より暗黙的/自動的にキャストします。

4

2 に答える 2

9

問題は、myTypesリストが として宣言されていることです。これは、リスト内の特定のパラメーター化ではなく、生の型List<MyType>を使用します。これは一般的に推奨されず、警告され、悪い習慣などです。 MyTypeMyType

List<MyType<String>>通常、リストはorのように宣言しますList<MyType<Integer>>。これにより、キャストせずに要素を取得できます。ただし、同じリストにMyType<String>とを混在させたいため、これには問題があります。繰り返しますが、これは一般的に推奨されておらず、コードの臭いです。MyType<Integer>

したがって、代わりにa を宣言できList<MyType<?>>ます。これは よりも優れていますがList<MyType>、それほどではありません。唯一の正しい結論は、設計に本質的な欠陥があるということです。コレクションに異種の型を混在させようとしないでください。


クラス MyType は単なる抽象的な例です。実際、私の質問はどのようにキャストできるかということでした: user.setName((user.getName().getClass()) object);if object is Object object = "foobar";

とにかく、問題は基本的に、リストで生の型を使用しているということです。Map<Class<T>, MyType<T>>a の代わりに aなど、型のパラメーター化を維持するものを使用した方がよいようですList<MyType>

ここで戦略パターンを適用することを検討してください。


*エキスパート モード: 上限として使用できる実用的な共通スーパータイプがない場合。

于 2013-02-23T15:43:59.047 に答える
3

Matt Ball の回答に 100% 同意します。理想的なものではないかもしれませんが、シンプルで迅速な解決策は、MyType から抽象性を取り除き、値を特定の型として取得する機能を追加することです。この種のパターンは、標準ライブラリのResultSetなどに見られます。

public class MyType {
    private String content;
    MyType(String content) { this.content = content }
    public String getStringValue() { return content; }
    public Integer getIntValue() { return Integer.parseInt(content); }
}
于 2013-02-23T15:52:13.513 に答える