Я пытаюсь определить класс (или набор классов, реализующих тот же интерфейс), который будет вести себя как свободно типизированный объект (например, JavaScript). Они могут хранить любые данные, а операции с ними зависят от базового типа.Лучшая практика Java для разрешения типа во время выполнения
У меня есть три разных способа, но никто не кажется идеальным. Эти тестовые версии допускают только строки и целые числа, и единственная операция добавляется. Добавление целых чисел приводит к сумме целочисленных значений, добавление строк объединяет строки и добавление целого числа в строку преобразует целое число в строку и объединяет его со строкой. Окончательная версия будет иметь больше типов (парные разряды, массивы, объекты, похожие на 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 общественности Строка 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
Way 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());
}
}
}
С, если-иначе логика я мог бы использовать value.getClass() == Integer.class вместо хранения типа, но с большим количеством типов я бы изменил это, чтобы использовать оператор switch, а Java не позволяет коммутатору использовать классы.
В любом случае ... Мой вопрос в том, что это лучший способ сделать что-то подобное?
Кстати, если мои знания Java не мешают мне, 'Class c = d.getClass(); if (c == DynInteger2.class) 'может быть записано как' if (d instanceof DynInteger2) ' – Thomas