Общий возврат
-
21-08-2019 - |
Вопрос
есть неизменный сорт:
Scope<Cmp extends Comparable<Cmp>>
public Scope<Cmp> crop(Scope<Cmp> scope) {
...
return new Scope<Cmp>(starts, ends);
}
в нем есть много подобные методы расширяются за счет:
Timerange extends Scope<Date>
и много другие (также неизменяемые).
Я бы хотел, чтобы они возвращали объект своего типа.Например:
timerange.crop(scope)
должен возвращать объект Timerange, а не Scope.
Нужно ли мне переопределять каждый метод (или использовать отражение)?Есть ли другой способ сделать это?
Заранее спасибо, Etam.
Решение
Вам нужен какой-то завод.В этом случае фабричный метод работает нормально.
public abstract class Scope<E extends Comparable<E>> {
abstract Scope<E> create(E start, E end);
public Scope<E> crop(Scope<E> scope) {
...
return create(starts, ends);
}
}
public TimeRange extends Scope<Date> {
Scope<Date> create(Date start, Date end) {
return new TimeRange (...);
}
}
Возможно, вы захотите добавить общий параметр this в базовый класс:
public abstract class Scope<THIS extends Scope<THIS, E>, E extend Comparable<E>> {
abstract THIS create(E start, E end);
public THIS crop(Scope<E> scope) {
...
return create(starts, ends);
}
}
public TimeRange extends Scope<TimeRange,Date> {
TimeRange create(Date start, Date end) {
return new TimeRange (...);
}
}
Это добавляет дополнительную работу в клиентский код.
Другие советы
Вы можете попробовать следующее:
class Scope<Cpm extends Comparable<Cpm>, Derived extends Scope<Cpm, Derived>> {
public Derived crop(Scope<Cmp, Derived> scope)
}
TimeRange будет определяться как
class TimeRange extends Scope<Date, Timerange>
и так crop
вернет объект TimeRange.Если производный класс не определен, вы можете использовать общие подстановочные знаки (Scope<Date, ?>
)
В Java нет возвращаемых значений собственного типа, поэтому обычно вам приходится вручную переопределять каждый метод.Видеть мой блог о «самотипах» для обсуждения некоторых возможных альтернатив.
Вам действительно нужно Timerange
?Предлагает ли он что-то большее, чем просто Scope<Date>
?Если нет, то просто используйте Scope<Date>
.
Другое предложение заключается в том, что вместо создания экземпляра с помощью конструктора вы можете клонировать объект, а затем соответствующим образом изменить поля для нового объекта.Причина в том, что клонированный объект имеет тот же тип, что и оригинал.
Scope<Cmp extends Comparable<Cmp>> implements Cloneable
public Scope<Cmp> crop(Scope<Cmp> scope) {
...
Scope<Cmp> result = (Scope<Cmp>)super.clone();
result.init(starts, ends); // sets the fields for a cloned object
// init() could be private
return result;
}