2015-03-09 2 views
2

У меня есть абстрактный класс java под названием FooFactory. Один из этих методов - withDate, который, очевидно, указывает на то, что я хочу в конечном итоге построить реализацию Foo с данной датой.Как написать метод для абстрактного класса, который возвращает тип реализации?

Мой вопрос в том, что. Как вернуть экземпляр моей реализации FooFactory из withDate? Вот то, что я пробовал:

abstract class FooFactory<T extends FooFactory<T>> 
{ 
    private date; 

    public T withDate(Date date) 
    { 
     this.date = date; 
     // Does not work 
     return this; 
    } 

    public abstract Foo build(); 

    // more with methods and a build method 
} 

То, что я хотел бы сделать, это то, чтобы иметь что-то вроде этого:

public final class BarFooFactory extends FooFactory<BarFooFactory> 
{ 
    @Override 
    public BarFoo build() 
    { 
     BarFoo barFoo = new BarFoo() 
     super.populateFooProperties(barFoo); 
     return barFoo; 
    } 
} 

Для тех, кому интересно, почему я просто не хочу, чтобы вернуть FooFactory, то причина в том, что компилятор будет интерпретировать будущее с вызовами и вызовами сборки в контексте FooFactory, и поэтому я не смог бы по-настоящему связать вызовы.

Является ли это тем, что я хочу сделать даже возможным?

+0

Не следует ли расширять 'BarFooFactory'' FooFactory'? Кроме того, почему вы используете дженерики - я не вижу здесь своей цели. –

+0

Да. Исправлена. Причина использования дженериков заключается в том, что я могу повторно использовать логику в классе FooFactory на других фабриках, которые возвращают реализации Foo. –

ответ

3

Решение, которое я видел применительно к аналогичным проблемам, заключается в определении абстрактного метода getThis(), который возвращает экземпляр подкласса. Он избегает неконтролируемого предупреждения о броске, но может ранить некоторых пуристов.

abstract class FooFactory<T extends FooFactory<T>> { 
    private Date date; 

    public abstract T getThis(); 

    public T withDate(Date date) { 
    this.date = date; 
    return getThis(); 
    } 
+0

Интересное решение. Это позволит избежать предупреждения о том, что @Makoto находит тревогу в моей версии решения. –

+1

Вы можете избежать абстрактного метода с помощью простого и безопасного литья ... –

3

Выяснил это. Мне просто нужно было отбросить «это» до Т при возвращении. Таким образом, код выглядит примерно так:

abstract class FooFactory<T extends FooFactory<T>> 
{ 
    private date; 

    public T withDate(Date date) 
    { 
     this.date = date; 
     // This works 
     return (T) this; 
    } 

    public abstract Foo build(); 

    // more with methods and a build method 
} 

Теперь new BarFooFactory().withDate(new Date()) Возвращает BarFooFactory вместо FooFactory.

+0

Это довольно тревожно; вы получите непроверенный бросок для этой операции. – Makoto

+2

@ Makoto Но это было бы совершенно безопасно. Мы можем добавить аннотацию '@ SuppressWarnings'. Или используйте 'getThis()' подход, как и в другом ответе. –

+1

Я не уверен, почему это вызывает беспокойство. Я могу подавить предупреждение, и я не буду плохо себя чувствовать, поскольку я уверен, что актер всегда будет работать. Если есть способ написать код, который расширяет FooFactory, когда такой трансляции не будет работать, мне было бы интересно увидеть его. –

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