我在读到有很多理由在 SO 线程和arcticle中制作一个最终类 ,其中两个是
1. To remove extensibility
2. to make class immutable.
使类不可变是否具有最终的特征(它的方法)?我看不出两者有什么区别?
我在读到有很多理由在 SO 线程和arcticle中制作一个最终类 ,其中两个是
1. To remove extensibility
2. to make class immutable.
使类不可变是否具有最终的特征(它的方法)?我看不出两者有什么区别?
不可变对象不允许改变他的状态。Final 类不允许继承自身。例如类Foo
(见下文)是不可变的(状态,即_name
永远不会改变)和类 Bar 是可变的(rename
方法允许改变状态):
final class Foo
{
private String _name;
public Foo(string name)
{
_name = name;
}
public String getName()
{
return _name;
}
}
final class Bar
{
private String _name;
public Bar(string name)
{
_name = name;
}
public String getName()
{
return _name;
}
public void rename(string newName)
{
_name = newName;
}
}
有时将类型识别为“可验证的深度不可变”可能很有用,这意味着静态分析可以证明(1)一旦构造了实例,它的任何属性都不会改变,以及(2)它持有的每个对象实例引用是可验证的深度不可变的。对扩展开放的类不能是可验证的深度不可变的,因为静态分析器无法知道是否可以创建可变子类,以及对该可变子类的引用存储在应该是可验证的深度不可变对象中。
另一方面,有时将抽象(因此可扩展)类指定为深度不可变是有用的。抽象类无法强制派生类不可变,但任何可变派生类都应被视为“损坏”。这种情况有点类似于要求两个相互报告自己“相等”的对象实例应该报告相同的哈希码。可以设计违反该要求的类,但是导致的任何错误的哈希表行为都是损坏的哈希码函数的错误,而不是哈希表的错误。
例如,可能有一个抽象的 ImmutableMatrix 属性,该属性带有一种在给定(行、列)位置读取元素的方法。一种可能的实现是使用 N*M 元素的数组来支持 NxM ImmutableMatrix。另一方面,定义一些子类(如 ImmutableDiagonalMatrix)也可能很有用,其中包含 N 个元素的数组,其中Value(R,C)
R!=C 将产生 0,并且Arr[R]
对于 R==C。如果一个正在使用的数组的很大一部分将是对角数组,则可以为每个这样的实例节省大量内存。虽然让类可扩展会留下有人可能以对变异开放的方式扩展它的可能性,但它也会留下可能知道程序使用的许多数组适合某种特定形式的程序员可以设计一个类以最佳方式存储该表单。