我经常在此站点上看到有关覆盖getPreferredSize()
的建议,而不是使用例如前面这些线程中所示的setPreferredSize()
的建议。
请参阅以下示例:
public class MyPanel extends JPanel{
private final Dimension dim = new Dimension(500,500);
@Override
public Dimension getPreferredSize(){
return new Dimension(dim);
}
public static void main(String args[]){
JComponent component = new MyPanel();
component.setPreferredSize(new Dimension(400,400));
System.out.println(component.getPreferredSize());
}
}
setPreferredSize()
getPreferredSize()
因此,这样做显然会破坏Liskov Substitution Principle。
prefferedSize
是一个绑定(bind)属性,因此当您设置它时,将执行firePropertyChange
。所以我的问题是,当您覆盖getPrefferedSize()
时,也不需要覆盖setPreferredSize(..)
吗?例子:
public class MyPanel extends JPanel{
private Dimension dim = null;
@Override
public Dimension getPreferredSize(){
if(dim == null)
return super.getPreferredSize();
return new Dimension(dim);
}
@Override
public void setPrefferedSize(Dimension dimension){
if(dim == null)
dim = new Dimension(500,500);
super.setPreferredSize(this.dim); //
}
public static void main(String args[]){
JComponent component = new MyPanel();
component.setPreferredSize(new Dimension(400,400));
System.out.println(component.getPreferredSize());
}
}
现在我们看到我们得到了相同的结果,但是监听器将收到实际值的通知,此外,我们不会破坏LSP,因为
setPreferredSize
状态为Sets the preferred size of this component.
,但不是方法。 最佳答案
这个有趣问题的几个方面(疯子已经提到了我的同伴开发者)
我们是否仅覆盖getXXSize()(也与setXXSize()一样)违反了LSP?
如果我们没有正确执行操作,则不是这样:-)第一权限是属性的API文档,最好是从属性的起源开始,即Component:
这是一个有约束力的契约(Contract),因此,我们实现的 setter/getter 必须遵守常量(如果设置):
@Override
public Dimension getPreferredSize() {
// comply to contract if set
if(isPreferredSizeSet())
return super.getPreferredSize();
// do whatever we want
return new Dimension(dim);
}
XXSize是一个绑定(bind)属性-是吗?
在JComponent的祖先中,仅存在间接证据:实际上,Component在setter中触发PropertyChangeEvent。 JComponent本身似乎在记录事实(由我自己负责):
……这是很明显的错误:绑定(bind)属性意味着值更改时需要通知监听器,即必须通过以下操作(伪测试):
JLabel label = new JLabel("small");
Dimension d = label.getPreferredSize();
PropertyChangeListener l = new PropertyChangeListener() ...
boolean called;
propertyChanged(...)
called = true;
label.addPropertyChangeListener("preferredSize", l);
label.setText("just some longer text");
if (!d.equals(label.getPreferredSize())
assertTrue("listener must have been notified", l.called);
...但是失败了。由于某种原因(不知道为什么这样认为合适),他们希望xxSize的常量部分成为绑定(bind)属性-这样的覆盖根本不可能。可能是一个(历史性的猜测)一个历史性的问题:最初,该安装程序仅在Swing中可用(出于充分的理由)。在向awt的反向移植中,它突变为从未有过的bean属性。
关于java - 重写getPreferredSize()会中断LSP,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21052894/