gpt4 book ai didi

java - 覆盖 getPreferredSize() 会破坏 LSP

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:56:28 25 4
gpt4 key购买 nike

我总是在这个网站上看到覆盖 getPreferredSize() 而不是使用 setPreferredSize() 的建议,如这些先前线程中所示。

  1. Use of overriding getPreferredSize() instead of using setPreferredSize() for fixed size Components
  2. Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
  3. Overriding setPreferredSize() and getPreferredSize()

看这个例子:

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()

  • Sets the preferred size of this component.

getPreferredSize()

  • If the preferredSize has been set to a non-null value just returns it. If the UI delegate's getPreferredSize method returns a non null value then return that; otherwise defer to the component's layout manager.

这样做显然会破坏 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 状态 设置此组件的首选大小。 但不是如何。

最佳答案

这个有趣问题的几个方面(Mad 已经提到了 spare-my-fellow-developer)

我们是否在仅覆盖 getXXSize() 时违反了 LSP(相对于 setXXSize() 也是如此)?

如果我们做对了 :-) 第一个权威是属性的 API 文档,最好从它的来源开始,即组件:

Sets the preferred size of this component to a constant value. Subsequent calls to getPreferredSize will always return this value.

这是一个有约束力的契约(Contract),因此无论我们如何实现 getter,它都必须遵守 constant 值(如果已设置):

@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 本身似乎记录了这个事实(由我加粗):

@beaninfo preferred: true bound: true description: The preferred size of the component.

这是……完全错误的:作为绑定(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 的 constant 部分成为绑定(bind)属性——这样的覆盖根本不可能。可能(当然是胡乱猜测)一个历史问题:最初,setter 仅在 Swing 中可用(出于充分的理由)。在它向 awt 的反向移植中,它变成了一个从未有过的 bean 属性。

关于java - 覆盖 getPreferredSize() 会破坏 LSP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21052894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com