0

プリティプリントと呼ばれる関数を実装するインターフェイスFeatureValueがあります。

現在、そのインターフェイスを実装する2つのクラスがあります。FeatureStringとFeatureList(FeatureListのリストには文字列が含まれています)。これらのクラスは、文字列とリストをそれぞれ格納し、ラップされた値に対してプリティプリント関数を実装する単なるラッパーです。

機能タイプの列挙型(文字列に対応するものとリストに対応するもの)をキーとして受け取るEnumMapがあります。

私はもともとこのインターフェースを作成したので、列挙型を繰り返し処理してきれいに印刷することができました。しかし、ラッパーのFeatureValueからも値を取得できるようにしたいと思います。

列挙型マップをとして保存している<Feature, FeatureValue>ので、ラップされた値がどのタイプであるかがわからないため、取得時にキャストする必要があります。

キャストする必要がないようにコードをリファクタリングする方法はありますが、タイプを知らなくても列挙型を繰り返し処理して出力する機能は保持されますか?

列挙型

public enum Features
{
KIND("kind"),
RULE("rule"),
PROBLEM("problem"),

private String name;

Features(String name)
{
    this.name = name;
}

public String getName()
{
    return name;
}
}

インターフェース

public interface FeatureValue
{
    public String prettyPrint();
}

リストの実装(FeatureStringにも同様のものがありますが省略します)

public class FeatureList implements FeatureValue
{
private final List<String> list;

public FeatureList(List<String> list)
{
    this.list = list;
}

@Override
public String prettyPrint()
{
    return Arrays.toString(list.toArray());
}

public List<String> getList()
{
    return list;
}
} 

キャストコード

for(String token: ((FeatureList) enumMap.get(Feature.particularFeatureThatCorrespondsToLists)).getValue())
    doSomething(token);

マップはFeatureListではなくFeatureの値に対してパラメータ化されているため、キャストが必要です。

4

2 に答える 2

0

getValue()メソッドをインターフェースに追加しFeatureValue、インターフェースをパラメーター化します。

FeatureValue.java

public interface FeatureValue<E> {

    String prettyPrint();    

    E getValue();

}

FeatureList.java

public class FeatureList implements FeatureValue<List<String>> {    

    private final List<String> list = new ArrayList<String>();

    public String prettyPrint() {
        return list.toString();
    }

    public List<String> getValue() {
        return list;
    }

}

Main.java

public static void main( String[] args ) {
    for (String each: getAsList(enumMap, Features.KIND)) {
        // do stuff
    }
}

private static List<String> getAsList(
        EnumMap<Features, FeatureValue> enumMap, Features key) {
    FeatureValue value = enumMap.get(key);
    return value != null ? 
       ((FeatureList) value.getValue()).getValue() : Collections.EMPTY_LIST;
}
于 2012-12-18T23:57:09.457 に答える
0

あなたの

public interface FeatureValue
{
    public String prettyPrint();
}

このように反復可能

public interface FeatureValue extends Iterable<String>
{
    public String prettyPrint();
}

FeatureValueこれにより、 foreach ループによってanyが反復可能になります。

実際に反復を必要としないクラスの場合は、例外をスローします

public class Stubbed1 extends FeatureValue {
    public Iterator<String> getIterator() {
        throw new UnsupportedOperationException();
    }
}

または空のイテレータを返します

public class Stubbed2 extends FeatureValue {
    public Iterator<String> getIterator() {
        return Collections.<String>emptyList().iterator();
    }
}

反復が必要なクラスの場合、次のことを行います

public class DocumentFeatureList implements FeatureValue
{
   private final List<String> list;

   ...

   public Iterator<String> getIterator() {
       return list.iterator();
   }
}
于 2012-12-19T00:05:06.263 に答える