2010-08-30 3 views
7

я продолжаю возвращаться к вариантам этой проблемы: она, вероятно, имеет очень простое решение, но я не могу понять это ...Возвратившись объект подкласса от суперкласса метода

У меня есть куча классов вида 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; 
} 

Можно ли придумать более экономной код - это еще тип- безопасно? ТИА

ответ

8

Вы можете использовать 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; 
    } 
} 

И первоначальный вопрос, это действительно плохая идея (и плохой практика), чтобы иметь суперкласс, который использует один из своих подклассов.


Ресурсы:

На эту же тему:

+0

Лучше (яснее, когда у вас много дженериков), чтобы назвать дженерики чем-то ближе к T_DimensionQuantity – Egwor

+0

Вы забыли абстрактное ключевое слово. ;) Просто использование «Т» довольно стандартная практика, я думаю. – Michael

+0

@mangst спасибо, теперь он абстрактный. @Egwor, как сказал @mangst, T распространен. T для типа, в коллекции это E для элемента, в Map это K и V для ключа и значения. Обычно это первая буква вашего родословного значения. –

0

В 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); 
    } 
} 
+0

Но теперь вы можете добавить AreaQuantity в свое DistanceQuantity. –

+0

Да, но это приведет к исключению ClassCastException. Поэтому это действие запрещено и будет обнаружено быстро (но во время выполнения, а не в компиляции). –

+0

Это действительно опасно, и если вы отдадите свое DistanceQuantity в DimensionQuantity, вы даже не знаете, что делать, не рискуя CCE. –

0

Создать перечисление для Размеры:

общественное перечисление Dimension {AREA, РАССТОЯНИЕ, ...}

выбрасывайте подклассы. Вместо этого создавайте только объекты DimensionQuantity и заставляйте каждого иметь (неизменяемый) размер, заданный во время создания.

Внесите дополнение в DimensionQuantity, сначала проверяя, что размеры добавленных двух величин одинаковы.

Voila! Меньшее количество классов, тип безопасности, отсутствие дубликата кода.

+0

«сначала проверяем, что размеры добавляемых двух величин одинаковы». Это звучит как время исполнения для меня! –

Смежные вопросы