Java运行时类型解析的最佳实践

时间:2010-05-07 06:36:39

标签: java overloading dynamic-typing loose-typing

我正在尝试定义一个类(或一组实现相同接口的类),它将表现为松散类型的对象(如JavaScript)。他们可以根据底层类型保存任何类型的数据和操作。

我让它以三种不同的方式工作,但似乎没有一种理想。这些测试版本只允许字符串和整数,唯一的操作是添加。添加整数会产生整数值的总和,添加字符串连接字符串并向字符串添加整数会将整数转换为字符串并将其与字符串连接。最终版本将有更多类型(双打,数组,类似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();       public 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类似

方式3:

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不允许切换使用类。

无论如何......我的问题是什么是最好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

您要做的是double dispatch。您希望调用的方法既依赖于调用它的对象的运行时类型,又依赖于其参数的运行时类型。

Java和其他C衍生产品仅支持单一调度,这就是您需要像选项1中使用的visitor pattern这样的kludge的原因。这是实现它的常用方法。我更喜欢这种方法,因为它不使用反射。此外,它允许您将每个案例保留在自己的方法中,而无需使用大的“交换机”方法来执行调度。

答案 1 :(得分:0)

我会选择第二个选项,第三个选项,我最好使用泛型,所以你不要依赖那个Enum。通过第一个选项,您可以在余生中实施方法。无论如何,您可以使用“instanceof”运算符进行类匹配。