在接口和具体类中输入参数泛型

时间:2014-04-03 06:28:45

标签: java generics inheritance type-parameter

我正在创建这样的东西,并对java中泛型的使用感到震惊。

创意:制作人生成类型为T的内容,消费者包含命令对象,命令对象包含不同的调解器 。调解器包含主题类型的对象,并更新类型为T

的值

注意:我这样做是为了理解泛型如何在泛型类型的继承和泛型类接口和具体类中的类型参数定义的组合方面工作,所以请不要这样做。打扰设计的基本原理。

接口定义:

成分:

  1. IObserver

  2. 包含T型和IObserver对象的ISubject。

  3. IMediator保存ISubject类型的对象并输入T

  4. ICommand保存IMediator类型的对象并输入T

  5. IProducerConsumer保存T类和ICommand类型的对象。

  6. 对应的接口有一些具体的对象。 我定义了这样的接口:

    public interface IObserver<T>
    public interface ISubject<T,O extends IObserver<T>>
    

    直到现在。但现在问题就开始了。

    public interface IMediator<T,S extends ISubject<T,O>, O extends IObserver<T>>
    

    编译器迫使我这样做。我的意思是O extends IObserver<T>如上所述。所以,我猜测我不能像下面那样定义

    public interface IMediator<T,S extends ISubject<T,O extends IObserver<T>> >
    

    我总结说:内部类型参数定义不能像上面那样扩展。 所以,终于开心了 公共接口IMediator<T,S extends ISubject<T,O>, O extends IObserver<T>> 现在在ICommand开始乱七八糟了 public interface ICommand <T,M extends IMediator<T, ?, ?>>

    我现在很震惊编译器不接受我的许多可能性,即使我上面做了什么推论。我的意思是

    public interface ICommand <T,M extends IMediator<T, S, o>, S extends ISubject<T, IObserver<T>>,O extends IObserver<T>>
    

    无效。 我不想使用外卡我想告诉编译器一些更具体的内容。

    我的问题是:

    1. 我的推理是否正确,如ICommand定义。

    2. 如何解释上述案例研究。

    3. 假设我想插入T并且必须能够获得和放置,最好的定义是什么。

    4. 接口和实现类中类型参数定义的规则和关系是什么。

    5. 请解释一下?

1 个答案:

答案 0 :(得分:1)

具有绑定参数的泛型(无通配符)

  • 我的推理在ICommand定义中是否正确?

    不。有两个原因
    1. 您在将{o}传递给Mediator时写了一个小'o'。 (我想这只是打字错误。)
    2. 您将IObserver<T>代替O传递给ISubject,这肯定会导致参数绑定不匹配。

正确版本:

interface ICommand<T, M extends IMediator<T, S, O>, S extends ISubject<T, O>, O extends IObserver<T>>

  • 如何解释上述案例研究?

    1. 您需要了解的第一件事就是一个未知类型T和五个接口。
    2. 因此,您将拥有总计六个具体类型,这些类型必须逐步包含在接口声明中。 (你明确要求不要理解设计的理由。)
    3. 如果以正确的顺序编写它们,它就会变得更易于管理。

接口声明:

interface IObserver<T>

interface ISubject<T, O extends IObserver<T>>

interface IMediator<T, O extends IObserver<T>, S extends ISubject<T,O>>

interface ICommand<T, O extends IObserver<T>, S extends ISubject<T, O>, 
                   M extends IMediator<T, O, S>>

interface IProducerConsumer<T, O extends IObserver<T>, S extends ISubject<T, O>,
                   M extends IMediator<T, O, S>, C extends ICommand<T, O, S, M>>

  • 假设我想要插入T并且必须能够获取和放置,最好的定义是什么?

    1. 如果你想得到并放置T型对象,你可能需要的是接口串,其中只有一个参数T 。泛型将强制执行所有兼容,因为T将在任何地方被相同类型替换。
    2. 您当前的系统太僵硬。在实际场景中,你永远不会有这么多接口的实现(除非你在java中重新实现facebook),这样你就可以有很多可能的实现组合,并且你想确保兼容性。
    3. 泛型通过应用良好的限制来强制实施类型安全。但是你不应该仅仅因为你可以放置它们而设置限制。您正在失去代码的灵活性可读性可维护性
    4. 只有在需要时才应添加边界。他们不应以任何方式影响设计 在合同之间之后

可能有足够的方式:

interface IObserver<T>

interface ISubject<T>

interface IMediator<T>

interface ICommand<T>

interface IProducerConsumer<T>

  • 接口和实现类中类型参数定义的规则和关系是什么?

    1. 我能想到的接口和实现类中的类型参数之间的唯一关系是实现类必须提供类型来替换泛型类型参数。
    2. 在某些情况下,类型可以再次为泛型类型,在这种情况下,使用类引用或扩展该类的另一个类将提供具体类型的责任转发给代码。 甚至可能是递归的!
    3. 当您使任何类型参数绑定时,规则不是用语言编写的,而是您在此机制上应用所有规则。因此,只要您提供符合所有规则的类型,您就可以了。
    4. 更多规则表示更强大,但灵活性/可读性 。明智的交易也是如此。

两个简单的案例:

// General way
private class ProductObserver implements IObserver<Product> { }

private ProductObserver productObserver;

// Aspect oriented way
private class LoggerObserver<T> implements IObserver<T> { }

private LoggerObserver<Product> loggerObserver;

  • 最后,如果您有任何疑问,我建议您阅读 Angelika Langer (全面)Java Generics FAQ
  • 如果你继续这样做,你最终可能会发明一种设计模式。当你这样做时,别忘了与我们分享:D

希望这有帮助。
祝你好运。