2


Civilization 4というゲームから都市をシミュレートするプログラムを書いています。これを行うために、その都市が所有する各プロットの地形、リソース、改善などのタイプを表すいくつかの列挙型があります。

問題は、私の独立したユーティリティに受け入れられる必要があるものをゲームに追加する可能性のあるファン製の mod と互換性があるようにプログラムしたいということです。そこで、ロードされた mod によって定義された新しいタイプを保持する Enumスタイルクラスを作成することを考えました (Enum は実行時に変更できないため)。これは、ユーザーがロードする mod を入力したときに実行時に作成されます (これは txt ファイルです)。新しい追加を読み取るために解析されます)

実行時に作成および追加される列挙型をシミュレートする方法はありますか? 実行前に行われるため、静的メンバー変数は使用できないと思います...

4

5 に答える 5

2

enumインターフェースを実装することができます。

このようにして、定義した値を列挙型に含めることができますが、新しい値はインターフェイスを実装する任意のクラスにすることができます。


enum別の方法は、バイト コード ジェネレーターまたはコンパイラ API を使用して、実行時に を生成またはロードすることです。String を取得してコンパイルおよびロードしやすくするためのライブラリを作成しました。

http://vanillajava.blogspot.co.uk/2010_11_01_archive.html

于 2012-08-31T20:57:18.257 に答える
1

Java の列挙型は、既知のオブジェクトのセットが既知であり、コンパイル時に制限されることを言語が保証する単なるクラスです。実行時に新しい列挙型リテラルを追加する場合は、通常のクラスになります。

于 2012-08-31T20:54:19.083 に答える
1

列挙型の優れた点は、人間が読める名前をコードに記述して、バックグラウンドで数値としてコンパイルできることです。コンピューターは数値を好むためです。たとえば、次の列挙型を使用します。

enum Season { WINTER, SPRING, SUMMER, AUTUMN }

舞台裏では、WINTER は 0 (ゼロ)、SPRING は 1 などです。ランタイム コードでこの動作を再現するには、次のように文字列のリストを作成します。

List<String> seasons;
seasons = new ArrayList<String>();
seasons.add("Winter");
seasons.add("Spring");
...

そうすれば、季節[1]が「春」に等しいなど、アイテムを数値として参照できます。この答えは、この質問にアプローチする多くの方法の 1 つにすぎません。

于 2012-08-31T21:18:42.137 に答える
1

デフォルトでは、enum型には設定された数の値しかありません。型の値enumは実際には として宣言されておりstatic final、実行時にさらに追加する方法はありません。

そうは言っても、必要なものを実装するために使用できる他のパターンがあります。インターフェイスと登録システムの使用方法を見てみましょう。Terrainインターフェイスから始めます。

public interface Terrain {
    int getId();
    String getName();
    int getSightBonus();
}

enumDefaultTerrain: _

public enum DefaultTerrain implements Terrain {
    PLAINS(0, "Plains", 1),
    HILLS(1, "Hills", -1),
    MOUNTAINS(2, "Mountains", -2);

    private int id;
    private String name;
    private int sightBonus;

    private DefaultTerrain(int id, String name, int sightBonus) {
        this.id = id;
        this.name = name;
        this.sightBonus = sightBonus;
    }

    public int getId() {return id;}

    public String getName() {return name;}

    public int getSightBonus() {return sightBonus;}
}

そして、静的ユーティリティ クラスまたはシングルトンのいずれかである登録クラス。

public class TerrainManager {
    private static Map<Integer, Terrain> terrainsById = new HashMap<>();

    static {
        for (DefaultTerrain terrain : DefaultTerrain.values())
            register(terrain);
    }

    public static void register(Terrain terrain) {
        Integer id = terrain.getId();
        if (terrainsById.contains(terrain.getId()))
            throw new IllegalArgumentException("Terrain with id already exists: " + id);
        terrainsById.put(id, terrain);
    }

    public static Terrain getTerrainById(int id) {
        return terrainsById.get(id);
    }

    public static Set<Terrain> getAllTerrains() {
        return new HashSet<Terrain>(terrainsById.values());
    }
}

この最後のクラスで魔法が起こります。おそらくモッダーは、ゲームのワールド定義に「このタイルを使用する」というある種の識別子を持っているでしょう? この場合、私はそれを整数と呼びましたidが、実際には任意の型である可能性があり、Mapそれに応じて を変更するだけです。マップ読み込みコードでは、ワールド定義の ID を使用してTerrain. modder が新しいTerrainを追加するときは、それを実装Terrainして に登録するだけですTerrainManager

staticイニシャライザは、他のオブジェクトが追加される前にオブジェクトが追加されるようにしますDefaultTerrain。シングルトンを使用する場合、代わりにこれをクラス コンストラクターに入れることができます。

このパターンは、enumユーザーに追加してもらいたいさまざまなタイプに使用します。以外のほとんどすべてのタイプにも使用できますenum

于 2012-08-31T21:24:53.807 に答える
0

CGLIB が必要です。http ://cglib.sourceforge.net/

于 2012-08-31T20:53:19.273 に答える