首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用需要更专门的构造函数参数的组合来扩展类?

如何使用需要更专门的构造函数参数的组合来扩展类?
EN

Stack Overflow用户
提问于 2014-10-02 23:59:59
回答 1查看 948关注 0票数 2

我正在尝试在可能的情况下使用作文来扩展课程。但我遇到了一个特殊问题。

假设我有一个基类和一个扩展类。如果我们使用组合,并且希望注入依赖项,扩展类将接受基类的实例,而不是继承它:

代码语言:javascript
复制
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()方法在扩展类中使用这些依赖项。

但是,如果我们想专门化扩展类中所需的的子类型,那么会怎样呢?

如果我们使用继承,我们可以简单地将子类型传递给超类构造函数,如下所示:

代码语言:javascript
复制
public class Extending extends Base
{
    private ISomeDependencySubtype dependency;

    public Extending(ISomeDependencySubtype dependency)
    {
        super(dependency);
        this.dependency = dependency;
    }
}

但是如果我们使用作文,那么这就变得更加困难了。我想出了几种选择:

具有初始化方法,而不是基中的构造函数

代码语言:javascript
复制
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()方法,因此接口可能变得不清晰。在使用扩展类时,另一个程序员可能会假设,在将基本实例传递到扩展实例之前,必须对其调用init()。

添加泛型参数

代码语言:javascript
复制
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的哪个子类型被传递给它。泛型参数只存在于此特定场景中,尽管需要重构以适应它。

扩展内部的实例化库

代码语言:javascript
复制
public class Extending
{
    private ISomeDependencySubtype dependency;
    private Base base;

    public Extending(ISomeDependencySubtype dependency)
    {
        this.base = new Base(dependency);
        this.dependency = dependency;
    }
}

这意味着不能传递基本实例,这意味着不能注入依赖项。这是不灵活的原因,这可能是显而易见的大多数。

因此,我想知道人们认为使用组合来解决这个问题最可取的选择是什么(请不要基于继承的答案)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-03 02:35:39

这和所有协变量依赖的问题一样,是一个有点病态的问题,而且可能没有完美的解决方案。

除了您的解决方案之外,还可以只将Base的类型和ISomeDependency的一个实例传递给Extending的构造函数,并动态地实例化Base对象。

代码语言:javascript
复制
public class Extending {

    // Keep an additional copy (ugly and probably unsafe).
    final dependendcy dependendcy;
    final Base base;

    public Extending(final Class<? extends Base> cls,
                     final ISomeDependencySubtype dependendcy) throws Exception {
        this.dependency = dependency;
        this.base = cls.getConstructor(ISomeDependency.class).newInstance(dependency);
    }
}

这有一个明显的缺点,即您必须假设一个Base的适当构造函数,这个构造函数不能由Java的类型系统静态地强制执行。

如果您愿意的话,您还可以假设一个默认的构造函数(可能看起来更简单一些),然后使用依赖项调用一个init方法。我不喜欢init方法。这样,您将消除是否应该由调用方初始化Base的模糊性。

在我看来,所有依赖于对依赖项保持额外引用的解决方案都是不安全的,因为不能保证Base不会这样替换对象。

代码语言:javascript
复制
assert this.dependency == this.base.getDependency();

很可能会失败。当然,降低getDependency返回的引用并不安全,因为出于同样的原因,

代码语言:javascript
复制
assert this.base.getDependency() instanceof ISomeDependencySubtype;

也可能会失败。

即使Extending extends Base (你说你不想要),这个问题也没有好转。

泛型方法可以解决这个问题,但它为您购买了所有其他类型的问题。

因为我不认为一个完美的解决方案存在,它可能在很大程度上取决于实际的用例,哪个邪恶的接受。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26171449

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档