繁体   English   中英

将抽象类中的泛型属性定义为实现类的一种

[英]Defining generic property in abstract class as a type of the implementing class

假设我有一个类似的课程:

public abstract class Foo {
    public List<TypeOfImplementingClassHere> container;
}

因此,当另一个类实现它时,就像这样:

public class Bar extends Foo {
    public Bar(List<Bar> container) {
        this.container = container;
    }
}

我们可以有一个指向在其中找到Bar对象的容器的指针。 您可以用Java或C#做到这一点吗?

当然。

尝试这个。

public abstract class Foo<T extends Foo<T>> {

    public List<T> container;

    protected Foo() {
        enforceConstraints();
    }

    private void enforceConstraints() {
        boolean valid = true;
        try {
            valid =
                ((ParameterizedType) this.getClass().getGenericSuperclass())
                    .getActualTypeArguments()[0]
                    .equals(
                        this.getClass()
                    );
        } catch (ClassCastException cce) {
            valid = false;
        }
        if (!valid) {
            String name = this.getClass().getSimpleName();
            throw new IllegalImplementationException(
                    name + " must be declared as "+ "\"class " + name + " extends Foo<"+name+">\"");
        }
    }

    private static class IllegalImplementationException extends RuntimeException {
        IllegalImplementationException(String message) {
            super(message);
        }
    }
}

在C#中甚至更简单:

public class Foo<T> where T : Foo<T> {

    public List<T> container;

    protected Foo() {
        enforceConstraints();
    }

    private void enforceConstraints() {
        if (!this.GetType().Equals(typeof(T))) {
            String name = this.GetType().Name;      
            throw new IllegalImplementationException(
                name + " must be declared as " + "\"class " + name + " : Foo<" + name + ">\"");
        }
    }


}

public class IllegalImplementationException : Exception {
    public IllegalImplementationException(String message) : base(message) {}
}

当发送到生产环境时,可以删除enforceConstraints() 请注意,这会强制我们通过反射来限制通用参数,因为此处所需的类型限制在Java或C#中不可用。 因为我们通过反射完全强制执行约束,所以没有必要添加约束T extends Foo<T> ,但这可以防止滥用。 注意,在约束Foo<T extends Foo<T>您可以让Bar2 extends Foo<Bar1> Bar1 extends Foo<Bar1>Bar2 extends Foo<Bar1> ,尽管我们不希望第二种类型,因此为什么需要反射。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM