java - 涉及继承和泛型的 Java 泛型的用处是什么 extends self

标签 java generics

我找到了其泛型参数扩展自身的泛型(here)。不是很懂,一开始怀疑是错的,但是没有人提出来。我对此有一些疑问:

  1. 如何使用 Variant 泛型,你能举个例子吗?
  2. 这种泛型风格的好处或效果是什么。

这是从 ( here ) 中选取的泛型样式代码。

abstract class Base<T extends Base<T>> {

}

class Variant<T extends Variant<T>> extends Base<T> {

}

谢谢!

最佳答案

我想你在谈论 F-bounded types .我发现它们在两个层次结构直接相关的情况下非常有用。想到的最清晰的案例是构建器模式,它针对类的层次结构。在这种情况下,构建器层次结构也很有用。

一个例子可能会说明一些问题。考虑以下(非常刻板的)层次结构:

public abstract class Human {

    protected String name;

    protected int age;
}

public class Woman extends Human {

    protected String loveMovie;
}

public class Man extends Human {

    protected String soccerTeam;
}

现在,我们要为 ManWoman 创建生成器。我们可以为每个构建器实现一个构建器,复制设置 nameage 属性的方法。然而,由于 ManWoman 继承自 Human,我们可以有一个抽象的 HumanBuilder,并使我们的 WomanBuilderManBuilder 继承自它。这就是 F 有界类型派上用场的地方。

Human 类及其 HumanBuilder 如下所示:

public abstract class Human {

    protected String name;

    protected int age;

    public static abstract class HumanBuilder<H extends Human, 
                                              T extends HumanBuilder<H, T>> {
        protected String name;

        protected int age;

        @SuppressWarnings("unchecked")
        public T name(String name) {
            this.name = name;
            return (T) this;
        }

        @SuppressWarnings("unchecked")
        public T age(int age) {
            this.age = age;
            return (T) this;
        }

        protected void fill(H human) {
            human.name = this.name;
            human.age = this.age;
        }

        protected abstract H create();

        public final H build() {
            H human = this.create();
            this.fill(human);
            return human;
        }
    }
}

这将是 Woman 类及其 WomanBuilder:

public class Woman extends Human {

    protected String loveMovie;

    public static class WomanBuilder extends HumanBuilder<Woman, WomanBuilder> {

        protected String loveMovie;

        public WomanBuilder loveMovie(String loveMovie) {
            this.loveMovie = loveMovie;
            return this;
        }

        @Override
        protected void fill(Woman woman) {
            super.fill(woman);
            woman.loveMovie = this.loveMovie;
        }

        @Override
        protected Woman create() {
            return new Woman();
        }
    }
}

最后,这是 Man 类及其 ManBuilder:

public class Man extends Human {

    protected String soccerTeam;

    public static class ManBuilder extends HumanBuilder<Man, ManBuilder> {

        protected String soccerTeam;

        public ManBuilder soccerTeam(String soccerTeam) {
            this.soccerTeam = soccerTeam;
            return this;
        }

        @Override
        protected void fill(Man man) {
            super.fill(man);
            man.soccerTeam = this.soccerTeam;
        }

        @Override
        protected Man create() {
            return new Man();
        }
    }
}

这种方法节省了大量代码行,尤其是在实际用例中。

正如预期的那样,使用构建器不需要任何转换:

Man man = new Man.ManBuilder()
    .name("Joe")
    .age(29)
    .soccerTeam("Los Angeles Galaxy")
    .build();

Woman woman = new Woman.WomanBuilder()
    .name("Jane")
    .age(25)
    .loveMovie("Meet Joe Black")
    .build();

关于java - 涉及继承和泛型的 Java 泛型的用处是什么 extends self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33186850/

相关文章:

java - 如何在 JPanel 中创建带边框单元格的 JTable?

java - 使用 StAX 验证数字签名

generics - scala:如何创建一个通用类型,该通用类型是scala中所有数字类的子类型,以便它可以包含compare方法

c# - 在抽象方法中使用泛型

java - Java 中 CRTP 的替代方案

java - 将 url 与 View 名称映射

java - 向 JavaFX WebView(不是 Android)添加填充

java - 将缩放图像级别保存到文件

generics - 以通用方式操作 Scala 集合

c# - 从变量实例化泛型类型