如何创建一个抽象的、不可变的 class?

How can one create an abstract, immutable class?

这是简短的版本。首先也是最重要的:我希望我的 class 是不可变的。我知道 class 不能既是抽象的又是最终的。 我要问的是:有没有办法允许内部classes扩展和实现外部抽象class? 这可能不是实现我不变目标的最佳方法,所以如果有人有更好的设计,我很乐意听到。

我正在为矢量运算写一个 class -- 就像在物理学和工程学中,而不是编程意义上的。 (我也知道 JScience has a package 这种东西。我想自己写一个,并保持简单。)

我喜欢 Java 的几何包中使用的模式,其中可以使用两个精度级别之一创建 Line2D:float 或 double。

public abstract class Line2D {
    public static class Float extends Line2D { /* Implementation */ }
    public static class Double extends Line2D { /* Implementation */ }
}

这是我非常想在我的 class 中合并和扩展的功能,因此我创建了以下内容:

public abstract class Vector2D {

    public final static class Integer extends Vector2D {

        // Component length projected along x/y axis, respectively
        final private int i, j;

        public Integer( int i, int j ) {
            this.i = i;
            this.j = j;
        }

        public Object doStuff() { /* vector operations */ }
    }

    public final static class Float extends Vector2D {
        // Identical to Vector2D.Integer, except with floats
    }

    public final static class Double extends Vector2D { /* Same Idea */ }

    // Outer class methods and whatnot
}

显然,Vector2D.IntegerVector2D.FloatVector2D.Double 都是最终的。除了这些内部 class 之外,有什么方法可以使 Vector2D 成为所有内容的最终结果吗?

Is there a way to only allow inner classes to extend and implement the outer, abstract class?

我会选择另一种选择:使您的抽象 类 非 public 并且仅使 public 成为 final 实现 类。这是AbstractStringBuilder的情况,属于java.lang包,是abstractpublic,由StringBuilder和[=17=实现] 类,也就是public final.

下面是这些类的相关源码:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    //implementation details...
}

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence {
    //implementation details...
}

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence {
    //implementation details...
}

Is there a way to only allow inner classes to extend and implement the outer, abstract class?

是的,将外部 class 的构造函数设为私有。

示例:

abstract class MyAbstractClass {
    int i; // some property
    private MyAbstractClass(int i) {
        this.i = i;
    }

    public static class InnerConcrete extends MyAbstractClass {
        int j; // some other property
        public InnerConcrete(int i, int j) {
            super(i);
            this.j = j;
        }
    }
}

我认为我从未遇到过这种方法。工厂模式可能更灵活,并允许您将原本可能很大的 class 拆分为多个文件。抽象的包访问级别 class 可能也足够了。