Я продолжаю возвращаться к вариантам этой проблемы: она, вероятно, имеет очень простое решение, но я не могу понять это ...
У меня есть куча классов в форме xQuantity, например DistanceQuantity, AreaQuantity и т. д., которые расширяют класс DimensionQuantity. Теперь вы можете добавлять или вычитать DistanceQuantity или AreaQuantity и т. Д., Но вы не можете смешивать их, поэтому я думаю, что мне нужно иметь (короткие) методы сложения, вычитания и т. Д. В подклассах, но я хочу уменьшить любую логику дублирование до минимума. Однако мне нужно вернуть объект подкласса, а это кажется трудным сделать с помощью метода суперкласса. Я считаю, что это можно сделать с помощью рефлексии, но AFAIK вам все равно нужно выполнить приведение в конце метода подкласса, и мне сказали, что рефлексия может быть дорогой ... Лучшее, что я придумала до сих пор, это:
В DistanceQuantity (и других подобных):
public DistanceQuantity() {
}
public DistanceQuantity add(DistanceQuantity d1) {
DistanceQuantity dn = new DistanceQuantity();
Object o = super.add(dn, this, d1, DistanceUnit.REF_UNIT);
return (DistanceQuantity) o;
}
В DimensionQuantity (за вычетом некоторых менее значимых утверждений):
public Object add(DimensionQuantity dn, DimensionQuantity d1, DimensionQuantity d2,
AbstractUnit au) {
dn.unit = au;
dn.scalar = d1.scalar + d2.scalar;
dn.units = dn.scalar;
return dn;
}
Может кто-нибудь придумать более тонкий код - он все еще безопасен для типов? TIA
В Java 6 вы можете попробовать что-то подобное. Но использование дженериков также является хорошей идеей:
public abstract class DimensionQuantity {
protected int quantity;
public DimensionQuantity (int quantity) {
this.quantity = quantity;
}
public abstract DimensionQuantity add(DimensionQuantity dq);
}
public class DistanceQuantity extends DimensionQuantity {
public DistanceQuantity(Quantity quantity) {
super(quantity);
}
/*
* A sub-class as return type is authorized.
* If dq is not a DistanceQuantity, a ClassCastException is thrown, but you can change this.
*/
@Override
public DistanceQuantity add(DimensionQuantity dq) throws ClassCastException {
return new DistanceQuantity(this.quantity + (DistanceQuantity) dq.quantity);
}
}
Вы можете использовать Generics следующим образом:
public abstract class DimensionQuantity<T extends DimensionQuantity>{
public abstract T add(T parameter);
}
и вы расширяете его следующим образом:
public class DistanceQuantity extends DimensionQuantity<DistanceQuantity>{
public DistanceQuantity add(DistanceQuantity parameter){
//Whatever
return null;
}
}
И для первоначального вопроса, это действительно плохая идея (и плохая практика) иметь суперкласс, который использует один из своих подклассов.
Ресурсы:
На ту же тему:
Создайте перечисление для измерений:
public enum Dimension { AREA, DISTANCE,...}
Выбросьте свои подклассы. Вместо этого создавайте только объекты DimensionQuantity и заставляйте каждый из них иметь (неизменяемое) измерение, установленное во время создания.
Реализуйте добавление в DimensionQuantity, предварительно проверив, что размеры двух добавляемых величин совпадают.
Вуаля! Меньше классов, безопасность типов, отсутствие повторяющегося кода.