接口和具体类中的类型参数泛型



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

想法:生产者生产T类型的东西,消费者包含命令对象,命令对象包含不同的中介。中介器保存主题类型的对象并更新 T 类型的值

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

接口定义:

组成:

  1. IOb服务器

  2. ISubject,它包含类型为 T 和 IObserver 的对象。

  3. IMediator 保存类型为 ISubject 和类型 T 的对象

  4. ICommand 包含 IMediator 和 T 类型的对象

  5. IProducerConsumer 持有类型 T 和 ICommand 的对象。

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

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. 接口和实现的类中类型参数定义的规则和关系是什么?

请解释一下 ?

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

  • 我的推论是否像ICommand定义中那样正确?

    不。两个原因
    1. 您在将其传递给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

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

最新更新