Java继承与初始化

St.*_*rio 11 java inheritance

我正在阅读J. Bloch的Effective Java,现在我正在继承vs组成部分.据我所知,他说继承并不总是好的.

子类中脆弱性的一个相关原因是它们的超类可以在后续版本中获取新方法.假设程序依赖于其安全性,因为插入到某个集合中的所有元素都满足某些谓词.这可以通过 继承集合并覆盖每个能够 添加元素的方法来保证,以确保在 添加元素之前满足谓词.这可以正常工作,直到在后续版本中将能够插入元素的新方法添加到超类中.

但为什么它不起作用?超类只是Collection接口,如果我们添加一个新方法,我们只是一个编译时错误.那不是有害的......

JB *_*zet 19

假设某些库v1.0中有一个Collection超类:

public class MyCollection {
    public void add(String s) {
        // add to inner array
    }
}
Run Code Online (Sandbox Code Playgroud)

你继承它是为了只接受长度为5的字符串:

public class LimitedLengthCollection extends MyCollection {
    @Override
    public void add(String s) {
        if (s.length() == 5) {
            super.add(s);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

合同,这个类的不变量是它永远不会包含长度为5的String.

现在发布了该库的2.0版本,并开始使用它.基类被修改为:

public class MyCollection {
    public void add(String s) {
        // add to inner array
    }

    public void addMany(String[] s) {
        // iterate on each element and add it to inner array
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您的子类未经修改.现在您的子类用户可以这样做

LimitedLengthCollection c = new LimitedLengthCollection();
c.addMany(new String[] {"a", "b", "c"});
Run Code Online (Sandbox Code Playgroud)

因此,你的子类的合同就被打破了.它应该只接受长度为5的字符串,它不再存在,因为在超类中添加了一个额外的方法.

  • 正确.这会引起另一个问题.版本2.0可以委托给add(),你可以依赖它来仅在add()中进行检查,而3.0版本不再委托给add(),因此可以绕过你的检查. (2认同)