1

見た目よりも複雑ですが、私はそのようなことを試みる義務があると思います. 列挙型のプロトタイピングを使用して抽象親クラスを作成したい (おそらく 1 つの値のみで列挙型を宣言し、それがデフォルトのユニット化されたものになり、サブクラスから使用するいくつかのメソッドを宣言したい)、次に、抽象親を拡張して実際にまったく同じ列挙型を初期化するクラスを作成したい (これにより、親列挙型が実質的に非表示になることがわかっています)。

私はこのレベルの抽象化についてあまり知らないので、より実用的な解決策がある場合に備えて、問題の性質について説明します。列挙型に基づいて多くのコマンドを実装するクラスを含むファイルがたくさんあります。(例えば、class1 はオブザーバーを実装し、どのコマンドが選択されたかを決定するために enum ベースのスイッチを使用する update メソッドを持っています。他のクラスにも同じことが当てはまります)すべてのクラス (CommandSet など) で同じ名前を使用して、列挙型の内部メソッドを使用してヘルプ リストをシステムに出力できる汎用メソッドを親内に配置できるようにします。これで、すべてのクラスでまったく同じメソッドを書き直すことができることがわかりましたが、作成中のライブラリを他の人が拡張し続けることができるように、メソッドを抽象化したいのです!

うまくいけば、私が混乱しすぎたり、混乱しすぎたりせず、誰かが助けてくれることを願っています! :)

編集:コードのアイデアは次のとおりです(おそらく正しくありません):

  public abstract class Commands{
    enum CommandSet{ 
        // empty command, placeholder
        null_command ("command name", "command description");
        // the Strings used for name and description
        private final String name;
        private final String description;
        // constructor 
        CommandSet(String name, String description){
            this.name=name;
            this.description=description;
        }
        // get parameters
        public String getName(){
            return name;
        }
        public String getDescription(){
            return description;
        }
    }
    public void showHelp(){
        for (CommandSet i : CommandSet.values()) {
            printf(i.getName(),":",i.getDescription());
        }
    }
}

public class StandardCommads extends Commands implements Observer{
    // I want to change the enum here, just changing the values so that null_command ("command name", "command description") will get removed and I will add a dozen other values, but keep the methods that the parent had
    // update inherited from Observer
    @Override
    public void update(Observable observable, Object object) {
        // I want the commands inside the switch cases defined inside this class's enum 
        switch(CommandSet.valueOf(String.valueOf(object)){
            case command1: doStuff1();break;
            case command2: doStuff2();break;
            ...
            case commandN: doStuffN();break;
        }
    // other methods
    void doStuff1(){
        ...
    }
    ...
    void doStuffN(){
        ...
    }
}

public class NonStandardCommads extends Commands implements Observer{
    // Another set of commands here for the enum keeping the same methods it had in the parent

    // update inherited from Observer
    @Override
    public void update(Observable observable, Object object) {
        // Other set of commands inside this class used in the switch statement
        switch(CommandSet.valueOf(String.valueOf(object)){
            case Zcommand1: doStuffz1();break;
            case Zcommand2: doStuffz2();break;
            ...
            case ZcommandN: doStuffzN();break;
        }
    // other methods
    void doStuffz1(){
        ...
    }
    ...
    void doStuffzN(){
        ...
    }
}
4

2 に答える 2

3

不可能: Java 列挙型は、別のクラスを拡張することも、それ自体を拡張することもできません。

ただし、インターフェースを実装することはできます。おそらく、あなたはそれを有利に利用することができます。


列挙型について他に役立つことがあります。列挙型は不変ではありません。列挙型のフィールド値を変更できますが、JVM 全体で変更されます。

別のアプローチとして、サブクラスのインスタンスを列挙型のメソッドに渡し、列挙型にサブクラスをコールバックとして使用させて、列挙型の別のユーザーの列挙型からさまざまな機能を取得することもできます。

于 2012-10-06T10:23:00.077 に答える
2

いいえ、それはできません。

後でさらに定義を追加/拡張したり、列挙型インスタンスをインスタンス化したりする場合、Java列挙型は非常に迅速かつ確実にガスを使い果たします。(たとえば、データベースからロードし、静的にだけでなく、インスタンスメソッドで構成します。)

Java列挙型の動作/ま​​たはロジックも少し制限されています-プロパティを定義および設定できますが、静的に初期化できるものだけであり、ロジックは基本的なようです(主に参照または序数を他の定義された列挙型定数と比較するだけです)。

あなたができること:

整数Codeを使用して祖先CommandまたはAbstractCommandクラス実装し、それをサブクラス化して、具体的な値/追加コード/インスタンスのロードまたは構成などを定義できます。

さらにメリットがあれば、効率的なスイッチとディスパッチ(コードによる)に加えて、詳細/プロパティを定義したり、必要に応じてコマンドをインスタンス化したりすることができます。

基本的に、これは、Javaが列挙型をサポートする前に列挙型を定義するために使用した方法です。厳密に静的ではなく、値オブジェクトとして使用している可能性がありますが。

私の専門知識:

私は広範なコンパイラと型システムの作業を行い、ファイル型と関連するデータ/動作の列挙型を試しました。外側の限界を調査し、明確な境界に到達しました。

また、新しいUnknownFileType( "")をインスタンス化して、回答として返すことができるのも気に入っています。列挙型はそれを行うことができません。

例:

(コードはJava 7を使用しているように見えるため、intではなくStringでディスパッチします。これにより、構文上の「名前」と内部整数の「コード」の両方が必要になるよりも、コマンドの解決が容易になります。)

public static class Command {
  protected String code;
  protected String desc;
  public String getCode() {return code;}
  public String getDesc() {return desc;}
  public Command (String code, String desc) {
    this.code = code;
    this.desc = desc;
  }
  public String toString() {return code;}
}

public class StandardCommands {
  public static Command READ = new Command("READ", "read a record");
  public static Command CREATE = new Command("WRITE", "create a record");
  public static Command EDIT = new Command("WRITE", "modify a record");
}
public class FurtherCommands extends StandardCommands {
  public static Command LIST = new Command("LIST", "list all records");
}

public class QueryCommands extends FurtherCommands {
  public static class QueryCmd extends Command {
    protected String search;
    public String getSearch() {return search;}
    // constructor..
  }
  public static QueryCmd QUERY_EXAMPLE = new QueryCmd("QUERY", "example", "query for specified string");


  public static QueryCmd createQuery (String search) {
    return new QueryCmd( "QUERY", search, "query for specified string");
  }
}
于 2012-10-06T10:49:24.587 に答える