2015-04-06 92 views
1

我試圖保持以下方式(這可能是錯誤的本質)節點屬性:通用對象的集合。自動鑄造?隱藏的鑄造?

public class Property<T> { 
    protected String key; 
    protected T value; 

    public Property(String key, T value) { 
     this.key = key; 
     this.value = value; 
    } 
} 


public class Node { 
    protected HashMap<String,Property> properties; 

    public Node() { 
     properties = new HashMap<>(); 
    } 

然而,這使我鑄造的巨型亂七八糟的不幸的副作用。我一直在閱讀所有可能相關的內容,但似乎沒有解決essentail問題。這是我目前的想法:

public void add(String key, Object value) { 
     if (! (value instanceof Property)) { 
      value = new Property<>(key, value); 
     } 
     properties.put(key, (Property)value); 
    } 

    public long get(String key, long x) { 
     return (long)properties.get(key).value; 
    } 
    public long[] get(String key, long[] x) { 
     return (long[])properties.get(key).value; 
    } 
    public String get(String key, String x) { 
     return (String)properties.get(key).value; 
    } 
    // etc 

現在,這顯然是incrediably愚蠢,但我兜兜轉轉試圖簡單地能夠通過鑰匙搶到節點屬性,並根據按鍵可以放心它的類型。

就這麼簡單。 給定的密鑰必須對應給定類型,既可用於添加也可用於獲取

我真的覺得我誤解了Java的本質。

+0

您是否必須使用字符串鍵,或者自定義類型是否可以接受? –

+0

自定義類型可能沒問題。字符串鍵是任意的。 –

回答

0

由於節點類可以容納任何值類型的屬性,因此無論如何您都需要制定未經檢查的轉換。有沒有必要超負荷get功能,可以投給任何預期收益類型爲

@SuppressWarnings("unchecked") 
public <T> T get(String key) { 
    return (T) properties.get(key).value; 
} 

例子:

Node node = new Node(); 
node.add("x", 123); 
node.add("y", "ABC"); 
node.add("z", new Date()); 

int valueX = node.get("x"); // cast to integer and autobox to int 
String valueY = node.get("y"); // cast to String 
Date valueZ = node.get("z"); // cast to Date 

String valueFail = node.get("z"); // this will throw a ClassCastException 
3

試試這個

// a node representing things of type T 
public class Node<T> { 
    protected HashMap<String,Property<T>> properties; 

    public Node() { 
     properties = new HashMap<>(); 
    } 

    // add a T to the map 
    public void add(String key, T value) { 
     properties.put(key, new Property<T>(string, value)); 
    } 
} 

我擔心你的例子,到目前爲止,是一個「節點」看起來就像是一個HashMap條目頗多。更好的問題將是「你真的想做什麼」?

+0

啊,我似乎需要澄清我的問題。參見Sotirios的答案的第一部分。你的建議很好,但不是我想要做的 –

+0

嗨邁克爾 - 你沒有告訴我們你要做什麼,你告訴我們你是如何實施它的。這個數據結構的目的是什麼?你想要解決什麼樣的現實世界問題?還有其他模式可以幫助... –

+0

節點表示圖像中的形狀(通過計算機視覺獲取)。屬性是形狀名稱,大小,角度,填充等。 –

2

給定的鍵必須對應給定的類型,既可以用於添加也可以用於獲取。

假設你的意思爲String key成爲元素及其類型一個標識符,那麼你的運氣了,它只是與仿製藥是不可能的。一種選擇是爲每個已知屬性定義一個具有適當類型的字段/獲取器的自定義類。

如果你指的x參數,那麼你可以使用泛型做這樣的事情

public <T> T get(String key, T x) { 
    return (T) properties.get(key).value; 
} 

但這種設置你的各種ClassCastException。你的編譯器應該警告這一點。 (也請注意,你將無法直接使用原始類型。)

+0

有趣。我的意思是前者。這很不幸,但謝謝你讓我知道 –

0

雖然它需要一些編譯器無法證明的內部轉換,但可以編寫一個外部類型安全的實現是正確的。

class TypeSafeMap { 
    public static final class Key<T> { 
    // deliberately empty; we're knowingly using reference equality 
    } 

    private final Map<Key<?>, Object> map; 

    TypeSafeMap() { 
    this.map = new HashMap<>(); 
    } 

    public <T> T get(Key<T> key) { 
    return (T) map.get(key); // cast is safe, but the compiler can't prove it 
    } 

    public <T> void put(Key<T> key, T value) { 
    map.put(key, value); 
    } 
} 

class SomewhereElse { 
    static final Key<Integer> myIntKey = new Key<Integer>(); 
    static final Key<String> myStringKey = new Key<String>(); 

    public void doWhatever(TypeSafeMap myMap) { 
    int myInt = myMap.get(myIntKey); 
    String myString = myMap.get(myStringKey); 
    } 
} 

...也就是說,如果你事先知道整組按鍵,你可以(也應該)做適當地與輸入字段的自定義類,而不是試圖去擠整個事情到地圖類結構。

0
public class Node 
{ 
    public static void main (String[] args) 
    { 
     Node node = new Node(); 
     node.addProperty("a", 12L); 
     node.addProperty("b", "i'm a string"); 

     long number = node.getProperty("a"); 
     String string = node.getProperty("b"); 
    } 

    private Map<String, Object> properties = new HashMap<>(); 

    public void addProperty(String key, Object value){ 
     this.properties.put(key, value); 
    } 

    public <T> T getProperty(String key){ 
     return (T) this.properties.get(key); 
    } 
} 
0

的OP正試圖處理的集合不同的對象,所以泛型不是前進的方向。他想要做的是對集合中的每個特定對象進行類型安全處理。以下是如何使用訪問者模式來實現這一點。

// Implement this interface in something which needs to process 
// an item from the collection in a way specific to the type of that item 
interface Visitor { 
    void visit(Circle c); 
    void visit(Square s); 
} 

class Collection { 
    Map<String, Shape> shapes = new HashMap<>(); 

    void add(String key, Shape shape) { 
     shapes.put(key, shape); 
    } 


    // when you want to process what's behind a key, send in a visitor 
    void visit(String key, Visitor visitor) { 
     // ask the shape to be visited by the visitor 
     shapes.get(key).visit(visitor); 
    } 
} 


interface Shape { 
    void visit(Visitor visitor); 
} 


class Circle implements Shape { 
    void visit(Visitor visitor) { 
     // tells the visitor to treat this object as a circle 
     visitor.visit(this); 
    } 
} 

假設您想要從集合中繪製特定形狀的東西。

class DrawingVisitor implements Visitor { 
    void visit(Circle c) { 
     // use properties only a circle has to draw it 
     graphics2d.ellipse(c.getRadius(), c.getCenterPoint()); 
    } 

    void visit(Square s) { 
     graphics2d.rectangle(s.getTopLeft(), s.getBottomRight()); 
    } 
} 

有意義嗎?