簡體   English   中英

Java最佳實踐,用於在運行時進行類型解析

[英]Java Best Practice for type resolution at runtime

我試圖定義一個類(或實現同一接口的類集),該類將表現為松散類型的對象(如JavaScript)。 它們可以保存任何種類的數據,並且對它們的操作取決於基礎類型。

我有三種不同的工作方式,但似乎都不是理想的。 這些測試版本僅允許字符串和整數,並且唯一的操作是add。 添加整數會得到整數值的總和,添加字符串會串聯字符串,將整數添加到字符串會將整數轉換為字符串並將其與字符串連接。 最終版本將具有更多類型(雙精度,數組,可動態添加新屬性的類似JavaScript的對象)和更多操作。

方法1:

public interface DynObject1 {
  @Override public String toString();
  public DynObject1 add(DynObject1 d);
  public DynObject1 addTo(DynInteger1 d);
  public DynObject1 addTo(DynString1 d);
}


public class DynInteger1 implements DynObject1 {
  private int value;

  public DynInteger1(int v) {
    value = v;
  }

  @Override
  public String toString() {
    return Integer.toString(value);
  }

  public DynObject1 add(DynObject1 d) {
    return d.addTo(this);
  }

  public DynObject1 addTo(DynInteger1 d) {
    return new DynInteger1(d.value + value);
  }

  public DynObject1 addTo(DynString1 d)
  {
    return new DynString1(d.toString()+Integer.toString(value));
  }
}

...和DynString1類似

方式2:公共接口DynObject2 {@Override public String toString(); 公共DynObject2 add(DynObject2 d); }

public class DynInteger2 implements DynObject2 {
  private int value;

  public DynInteger2(int v) {
    value = v;
  }

  @Override
  public String toString() {
    return Integer.toString(value);
  }

  public DynObject2 add(DynObject2 d) {
    Class c = d.getClass();

    if(c==DynInteger2.class)
    {
      return new DynInteger2(value + ((DynInteger2)d).value);
    }
    else
    {
      return new DynString2(toString() + d.toString());
    }
  }
}

...和DynString2類似

方式三:

public class DynObject3 {

  private enum ObjectType {
    Integer,
    String
  };

  Object value;
  ObjectType type;

  public DynObject3(Integer v) {
    value = v;
    type = ObjectType.Integer;
  }

  public DynObject3(String v) {
    value = v;
    type = ObjectType.String;
  }

  @Override
  public String toString() {
    return value.toString();
  }

  public DynObject3 add(DynObject3 d)
  {
    if(type==ObjectType.Integer && d.type==ObjectType.Integer)
    {
      return new DynObject3(Integer.valueOf(((Integer)value).intValue()+((Integer)value).intValue()));
    }
    else
    {
      return new DynObject3(value.toString()+d.value.toString());
    }
  }
}

使用if-else邏輯,我可以使用value.getClass()== Integer.class而不是存儲類型,但是使用更多類型時,我將其更改為使用switch語句,並且Java不允許switch使用Classes。

無論如何...我的問題是做這樣的事情的最好方法是什么?

您要嘗試執行的操作稱為雙重調度 您希望所調用的方法既取決於被調用對象的運行時類型,又取決於其參數的運行時類型。

Java和其他C派生類僅支持單調度,這就是為什么您需要像在選項1中使用的訪問者模式那樣的麻煩。這是實現它的常用方法。 我更喜歡這種方法,因為它不使用反射。 此外,它允許您將每種情況都保留在自己的方法中,而無需使用大的“總機”方法進行分派。

我會選擇第二個選項,而在第三個選項中,我最好使用泛型,這樣您就不必依賴於該Enum。 使用第一個選項,您可以在余生中實現方法。 無論如何,您都可以使用“ instanceof”運算符進行類匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM