不可变的非最终课程

时间:2015-01-08 21:34:45

标签: java class immutability

如果一个类可以被子类化(但保留其他规则),那么它仍然被认为是不可变的吗? 例如:

abstract class Figure {
abstract double area();
}

class Rectangle extends Figure {
private final double length;
private final double width;

Rectangle(double length, double width) {
    this.length = length;
    this.width = width;
} 

double area() { return length * width; }
}

它是不可变的吗?

3 个答案:

答案 0 :(得分:2)

字段lengthwidth对于所有子类仍然是不可变的(如果它们没有被具有相同名称的子类字段遮蔽)。

但是一个子类可以定义它自己的可变字段。

所以答案是:这取决于。

如果你没有使用可变字段继承其他类Rectangle,那么答案是肯定的。 否则没有。

答案 1 :(得分:1)

  

不可变的非最终课程

不存在。

如果您的班级不是final,则可以将其划分为子类。

根据定义,不可变类只有不变量。但如果它不是final,则可以对其进行子类化并引入非变量的实例字段。所以:

public class A 
{
    private final int a;

    public A(final int a)
    {
        this.a = a;
    }
}

不是不可变的,因为你可以:

public class B
    extends A
{
    // NOT AN INVARIANT
    private int b;

    public B(final int a)
    {
        super(a);
    }

    public void setNonInvariant(final int b)
    {
        this.b = b;
    }
}

但是:类A线程安全的。但这不是一成不变的。类B不是线程安全的......

答案 2 :(得分:0)

如果基类本身在您的示例中是不可变的,那么是的,这是不可变的。在诸如Java这样不支持编译器强制不变性的语言中,它作为开发人员来处理它 - 并且基本上意味着任何不能将其状态改变的对象都被认为是不可变的。

在上面的示例中,您甚至不需要将变量设为最终 - 事实上没有任何东西可以改变它们意味着它是不可变的。