Я пытаюсь расширить классы, используя композицию, где это возможно. Но у меня проблемы с конкретной проблемой.Как вы расширяете класс, используя композицию, которая требует более специализированного аргумента конструктора?
Допустим, у меня есть класс Base и класс расширения. Расширение класса занимает в экземпляре класса Base, а не наследование от него, если мы используем состав, и мы хотим, чтобы ввести наши зависимости:
public class Base
{
private ISomeDependency dependency;
public Base(ISomeDependency dependency)
{
this.dependency = dependency;
}
public ISomeDependency getDependency()
{
return dependency;
}
}
public class Extending
{
private Base base;
public Extending(Base base)
{
this.base = base;
}
}
Базовый класс принимает в некоторой зависимости, мы можем использовать в Расширение класса с помощью метода getDependency().
Однако, если мы хотим специализировать, какой подтип ISomeDependency нам нужен в расширяющемся классе.
Если бы мы использовали наследование, мы могли бы просто передать подтип в конструктор суперкласса, как так:
public class Extending extends Base
{
private ISomeDependencySubtype dependency;
public Extending(ISomeDependencySubtype dependency)
{
super(dependency);
this.dependency = dependency;
}
}
Но если мы используем состав, то это становится все труднее. Я думал несколько вариантов:
Имея метод инициализации вместо конструктора в базе
public class Extending
{
private ISomeDependencySubtype dependency;
private Base base;
public Extending(Base base, ISomeDependencySubtype dependency)
{
base.init(dependency);
this.base = base;
this.dependency = dependency;
}
}
Эта опция скрывает тот факт, что расширяющий класс использует метод Init() на базе класс, поэтому интерфейс становится неясным. При использовании класса Extended другой программист может предположить, что экземпляр Base должен иметь init(), вызываемый на нем, прежде чем он будет передан в экземпляр расширения.
Добавление общий аргумент
public class Base<T extends ISomeDependency>
{
private T dependency;
public Base(T dependency)
{
this.dependency = dependency;
}
public T getDependency()
{
return dependency;
}
}
public class Extending
{
private ISomeDependencySubtype dependency;
private Base<ISomeDependencySubtype> base;
public Extending(Base<ISomeDependencySubtype> base)
{
this.base = base;
this.dependency = base.getDependency();
}
}
Это кажется как злоупотребление дженериков. Если базовый класс является классом в своем собственном праве и может использоваться без класса расширения, ему не нужно заботиться о том, какой подтип ISomeDependency ему передан. Общий аргумент будет существовать только для этого конкретного сценария, несмотря на все, что нужно будет реорганизовать для его размещения.
инстанцировании базы внутри Расширение
public class Extending
{
private ISomeDependencySubtype dependency;
private Base base;
public Extending(ISomeDependencySubtype dependency)
{
this.base = new Base(dependency);
this.dependency = dependency;
}
}
Это означает, что базовый экземпляр не может быть передан, в котором означает зависимость не может быть введен. Это негибкий по причинам, которые, вероятно, очевидны для большинства.
Поэтому я хотел бы знать, что люди считают самым предпочтительным вариантом, используя композицию для преодоления этой проблемы (без ответов на наследование).
Ваши примеры иногда содержат ложную 'extends Base'. – 5gon12eder
Хорошо пятнистый. Будет редактировать. – Jonathan