2016-08-17 10 views
2

私はプロパティのセットを表す次のクラスを持っています。オブジェクトの代わりに、マップ内でキャスト

public class Properties 
{ 
    /** String type properties. */ 
    private final List<String> m_stringProperties = Arrays.asList("str1", "str2", "str3"); 

    /** Float type properties. */ 
    private final List<String> m_floatProperties = Arrays.asList("float1", "float2", "float3"); 

    /** Integer type properties. */ 
    private final List<String> m_intProperties = Arrays.asList("int1", "int2"); 

    public class PropertyType 
    { 
     private final String m_name; 
     private final Object m_value; 

     public PropertyType(String name, Object value) 
     { 
      m_name = name; 
      m_value = value; 
     } 

     public String getName() 
     { 
      return m_name; 
     } 

     public Object getValue() 
     { 
      return m_value; 
     } 
    } 

    /** The container for the properties. */ 
    private final Map<String, PropertyType> m_properties = new HashMap<>(); 

    public PropertyType getProperty(String name) 
    { 
     return m_properties.get(name); 
    } 

    public void setProperty(String name, Object value) 
    { 
     if ((m_stringProperties.contains(name) && value instanceof String) 
       || (m_floatProperties.contains(name) && value instanceof Float) 
       || (m_intProperties.contains(name) && value instanceof Integer)) 
     { 
      m_properties.put(name, new PropertyType(name, value)); 
     } 

     else 
     { 
      assert false : "Invalid property name"; 
     } 
    } 
} 

ノート

  1. 各プロパティは名前と値があります。
  2. プロパティ値は、String型、Float型、Integer型のいずれかです。
  3. プロパティの名前は、クラスの先頭のリストに定義されている値に制限されています。
  4. 特定のプロパティは、そのプロパティ名に適切なタイプである場合にのみマップに追加できます。

    Properties properties = new Properties(); 
    
    // set properties 
    properties.setProperty("str1", "testId"); 
    properties.setProperty("float1", 1.0f); 
    
    // get properties 
    Properties.PropertyType str1 = properties.getProperty("str1"); 
    Properties.PropertyType float1 = properties.getProperty("float1"); 
    Properties.PropertyType invalid = properties.getProperty("unknown"); // return null 
    
    System.out.println("str1: " + str1.getValue()); 
    System.out.println("float1: " + float1.getValue()); 
    
    float f1 = (float) properties.getProperty("float1").getValue(); 
    Object o1 = properties.getProperty("float1").getValue(); 
    
    System.out.println("f1: " + f1); 
    System.out.println("o1: " + o1); 
    
    properties.setProperty("str1", 1.0f);  // assertion - str1 property should be String, not Float 
    

    私はこれを実装するためのより良い方法があるかどうかを知りたいのですが、次のように

クラスを使用することができます。具体的には、私はObjectの使用を避けたいと思います。私は、有効なJavaの項目20で説明されているように、パラメータ化されたクラスとジェネリック型、さらには型保証されていない異種コンテナを試しました。

getPropertyが呼び出された場合、戻り値が自動的に正しい型になるように、できるだけ型保証された、つまりコンパイラによる型チェックを実行したいと考えています。

私は種類ごとにsetPropertyをオーバーロードしてgetPropertyは、だけではなく、ネストされたタイプPropertyTypeObjectを返すことができますが、それはまだ<String, Object>のコンテナで私を残していることができることを実現しています。

私はC++のJava初心者です。 C++では、マップ値はboost::variantになります。

答えて

0

クラスが3つのタイプのうちの1つを受け取るようにするには、コンパイラがそれを熟知しているかどうかを確認するために、多態性を使用できます。

例:

public PropertyType(String name, String value) 
     { 
      m_name = name; 
      m_value = value; 
     } 

public PropertyType(String name, Integer value) 
     { 
      m_name = name; 
      m_value = value; 
     } 

public PropertyType(String name, Float value) 
     { 
      m_name = name; 
      m_value = value; 
     } 

文字列、整数および浮動小数点数は、オブジェクトを拡張するので、あなたは、変数private final Object m_value;

に彼らをキャストする必要はありません。しかし、あなたは変数の型をチェックする必要がある場合(例えば、createやvariableのように、3つの型のうちのどれかであるかどうかはわかりません)、これはうまくいかないかもしれません。

関連する問題