首先,这不是this question的重复,即使它们具有相同的标题。这个问题指的是与C函数基本相同的传递方法:它们不需要属于特定对象。在这种情况下,您可以传递Runnable
或Callable
对象。
相反,我问的是:是否可以在类中传递对特定方法的引用,并为特定对象调用该方法?
例如,我正在查看Swing中FlowLayout
的代码,并注意到preferredLayoutSize
和minimumLayoutSize
实现完全相同,除了一行:< / p>
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
boolean useBaseline = getAlignOnBaseline();
int maxAscent = 0;
int maxDescent = 0;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent, d.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
boolean useBaseline = getAlignOnBaseline();
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
int maxAscent = 0;
int maxDescent = 0;
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getMinimumSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent,
dim.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
preferredLayoutSize
方法调用preferredLayoutSize
的{{1}}方法(m
- 组件),而i
调用minimumLayoutSize
方法minimumLayoutSize
。据我所知,这两种方法在其他方面是相同的。
正如任何programmer会告诉你的那样,代码重复是一件坏事。然而,在这种情况下,如何摆脱重复的代码并不明显。很明显,应该有一个私有方法,其中包含公共方法调用的代码,并传递对m
类的preferredLayoutSize
和minimumLayoutSize
方法的引用。在C中我可以使用函数指针来做到这一点,所以在Java中应该有一些方法可以做到这一点。传入Component
或Runnable
几乎可以正常工作,但都不会返回值。 编辑:这是错误的。 Callable
中重写的方法返回一个值,它所作用的对象可以作为参数传入。
现在我输入了所有内容,我遇到了一个解决方案:您可以使用名为Callable
的方法编写interface
并编写两个实现,其中一个返回{{1} }和另一个返回Dimension layoutSize(Component comp)
。然后,您可以编写一个私有方法,将该接口的实例作为参数,并使用该方法在代码中的正确位置运行单独的方法。您甚至可以使用匿名内部类,因此您不必为每种类型的布局大小编写新类。不过,对于一个相当简单的问题来说,这似乎仍然很麻烦。有更简单的方法吗?
答案 0 :(得分:2)
您可以在类LayoutSizing
(可能是本地类)中包含其中一个方法,使用抽象方法在m
上进行计算,并将m
作为参数,然后在两种方法都使用实现的方法实例化new LayoutSizing() { @Override ... }
。
在Java 8中,希望看起来好一点。
答案 1 :(得分:2)
您可以使用界面:
interface DimensionReturningThingy {
public Dimension getDim (Component c);
}
public Dimension preferredLayoutSize(Container target) {
commonCode (target, new DimensionReturningThingy () {
public Dimension getDim (Component m) {
return m.getPreferredSize ();
});
}
// and similarly for minimumLayoutSize
public Dimension commonCode (Container target, DimensionReturningThingy drt) {
// now repeat code above, except that replace
Dimension d = m.getPreferredSize();
// with
Dimension d = drt.getDim (m);
我不擅长命名,所以我相信你可以为其中一些提出更好的名字。
编辑:我认为我在编辑您的原始帖子之前正在努力回答此问题,以提及界面解决方案。
答案 2 :(得分:1)
对于这种特殊情况,最简单的解决方案是将这两种方法重构为三种方法:
private Dimension layoutSize(Container target, boolean prederred) {
...
Dimension d = prederred?m.getPreferredSize():m.minimumLayoutSize();
...
}
public Dimension preferredLayoutSize(Container target) {
return layoutSize(target, true);
}
public Dimension minimumLayoutSize(Container target) {
return layoutSize(target, false);
}