【问题标题】:Generics vs. Interfaces泛型与接口
【发布时间】:2010-02-24 22:31:49
【问题描述】:

我从 Java 1.4(以前的公司)过渡到 Java 1.6(新公司)。我观察到,在 1.4 中,大多数专有框架是使用接口和模板模式定义的,而在 1.6 中,大多数框架都是围绕泛型定义的。

虽然我仍在尝试掌握泛型,但我的问题是 - 这是一种正确的设计方法吗?接口使您的设计更加灵活/解耦。而泛型则实现类型安全并强制您传递特定类型的类。对解耦代码没有帮助。它是否正确?

一个例子-

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{
}

如果是 ..,设计会更加灵活。

public interface Wizardable{
  public SignableSection getSection();
  public SignableObject getSignableObject();
...
}

public MyWizard implements Wizardable{
....
}

【问题讨论】:

  • 请改进您的示例。例如,SignupWizard 的定义是什么?给出一些框架的具体例子,其中泛型使用你所说的方式。 “泛型与接口”的问题对我来说没有多大意义,因为它们经常一起使用。 “注解与接口”更有意义。
  • 看起来像我在 C++ 中所期望的,而不是 Java。

标签: java generics interface


【解决方案1】:

我不会说什么是泛型与接口,每个都有不同的需求和用途。以原始帖子中提到的方式使用泛型参数有多种用途。它允许开发人员定义构成类的字段对象类型的基类。使用它,开发人员可以接受类对象作为参数,他们可以使用反射来创建实际对象并设置字段,或者首先接受整个对象进行设置。与需要类对象而不是做new T() 或类似的问题有关的问题被称为type erasure

使用泛型的另一个好处是,在使用超类中的字段或方法时,您不需要一直进行类型转换——您个人知道它们的类型,但 Java 没有将类型信息存储在任何地方。另一个好处是,您的所有 getter / setter 方法都可以使用通用参数,并向其他对象公开更明智的前端,这些对象依赖于您在上述对象中设置专门字段这一事实。

使用接口做与泛型相同的事情的问题是,您需要额外的方法来访问专门的类型并转换它们,然后再返回它们(或检查传入的类型,然后为对象设置字段)。它使设计变得更加复杂,并且对解耦没有任何帮助。

正如我在评论中提到的,任何子类都会设置这些类型参数,并且不会向用户公开任何内容。因此,您可以拥有类似class MegaSignupWizard extends SignupWizard&lt;MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView&gt; 的东西,并且在MegaSignupWizard 可以访问类中的专门方法而无需进行任何强制转换时,一切都保持完全有效。现在这很酷:)

【讨论】:

    【解决方案2】:

    泛型允许您在通用类型上实现方法,而接口仅定义签名。也许有时它被滥用以表现得像 Scala 的trait,但大多数情况下它们服务于两个不同的目的。如果一切都是一个接口,就会有很多重复的代码或对某个帮助类的委托。

    【讨论】:

      【解决方案3】:

      我注意到许多新框架倾向于使用注解而不是接口,但我没有注意到它们使用泛型而不是接口(无论是什么意思 - 请解释更多)。

      在泛型的帮助下,当您拥有一个带有泛型类型参数的接口并且同一接口适用于许多不同类型时,可以减少一些代码重复并提高类型安全性。 java.util 包中的集合是泛型有用的一个很好的例子。

      在注解的情况下,有时我觉得它们被过度使用并且接口会更好 - 例如使用接口很容易知道方法应该采用哪些参数 - 但在其他情况下,注解更灵活和强大。

      【讨论】:

      【解决方案4】:

      我认为它是泛型和接口,因为任何接口都可以使用泛型本身。当您开始使用通用(抽象)类时,我看到的问题是您失去了使用组合的灵活性。虽然继承本身并没有什么坏处,但您必须为它进行设计,但存在许多陷阱。

      【讨论】:

      • 是的,Bloch 在“Effective Java”中的观点之一是支持组合而不是继承。我的理论是,每当我看到泛型和抽象类的大量使用时,程序员对接口的熟悉程度不如他们对 Java 中最新的玩具(泛型、注释)的熟悉程度。因此,当我们将所有框架视为答案时,这并不一定意味着这是一条真正的道路。我猜只有时间才能证明他们的设计是否健壮且具有延展性,即是否会像 log4j 这样的东西存在。
      【解决方案5】:

      看看 Jung2,看看泛型在哪里变得真正强大。基本上,任何对象都可以是顶点或边,这在网络算法中产生了一些非常有趣的想法。仅使用接口无法做到这一点。

      我也不确定您的上述用途看起来不错。如果你从一个对象扩展或实现一个接口,你真的不想传递这样的对象。泛型用于实现具有抽象类型的类,如集合,它可以作用于任何东西。如果我通过完全有效的SignupWizard&lt;int, int, int, int&gt; 会发生什么?

      对于这个特定的想法,也许您确实想使用接口。有一个定义wizardaction的接口,每个实现它的对象和mywizard能够.addaction(int position,wizardaction action)。事实上,这绝对是一个接口问题。

      我同意其他人的观点 - 泛型已在库需要时使用。

      【讨论】:

      • 如果顶点和边有超接口,那么对象可以是顶点或边。
      • 但是你不能在边缘有类型的参数。您必须使用对象或坚持一种类型。
      • 完全有效。任何子类都将设置这些类型参数,并且不会向用户公开任何内容。因此,您可以拥有类似 MegaSignupWizard extends SignupWizard 之类的东西,并且 MegaSignupWizard 可以访问类中的专用方法,而无需进行任何转换,一切都保持完全有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      • 2011-03-14
      相关资源
      最近更新 更多