1

我有两个类:JDialog 和 JFrame(见下文)。现在我希望它们获得一些额外的功能,但我希望这两个类都扩展我的代码,而无需编写两次代码。有没有办法做到这一点?

java.awt.Window » java.awt.Dialog » javax.swing.JDialog  
java.awt.Window » java.awt.Frame » javax.swing.JFrame

(PS:实际上,我想“重写” 的源代码java.awt.Window,添加额外的功能。我知道这是不可能的,但这将是一个“解决方案”,因为如果我这样做,JDialog 和 JFrame 都会扩展我的全新方法。)

示例:
假设我想添加方法moveWindowToMagicPositionOnScreen(),将窗口移动到屏幕上用户友好的位置——我知道,这只是一个示例。我希望该方法同时适用于JDialogJFrame。使用继承,我必须编写两个类,例如MagicJDialogMagicJFrame,每个类都moveWindowToMagicPositionOnScreen()以完全相同的方式实现方法。嗯,这很多余。所以我不想让代码写两次。在某种程度上,我希望一个类使用另一个类的代码。

4

4 回答 4

1

不幸的是,Java 不支持 mixin。在这里采用的最简单和最清晰的方法是使用组合,在这种情况下,您只需要编写两次包装器,但实际的实现位于一个位置。

于 2012-06-30T04:47:01.223 回答
1

就像其他几个人建议的那样,更喜欢组合而不是继承。但是,您可以为您的方法创建一个通用接口:

public interface Magic {
    void moveWindowToMagicPositionOnScreen();
}

如果移动窗口的代码完全相同,则创建一个委托类:

public class MagicDelegate implements Magic {

    public void moveWindowToMagicPositionOnScreen() {
        // TODO implement logic
    };
}

然后让您的两个类Magic使用以下方法实现接口MagicDelegate

public MagicJDialog implements Magic {

    private MagicDelegate magicDelegate;   // TODO instantiate

    public void moveWindowToMagicPositionOnScreen() {
        magicDelegate.moveWindowToMagicPositionOnScreen();
    }
}

public MagicJFrame implements Magic {

    private MagicDelegate magicDelegate;   // TODO instantiate

    public void moveWindowToMagicPositionOnScreen() {
        magicDelegate.moveWindowToMagicPositionOnScreen();
    }
}

旁注,移动窗口的代码只有部分相同,您可以选择忽略MagicDelegate该类或创建具有公共部分的模板类:

public abstract MagicTemplate implements Magic {

    public moveWindowToMagicPositionOnScreen() {
        // common logic
        implementationSpecificLogic();
        // more common logic  
    }

    protected abstract void implementationSpecificMethod();
}

现在,MagicJDialog类和MagicJFrame类可以扩展MagicTemplate类并实现implementationSpecificLogic()方法。

于 2012-06-30T06:00:37.943 回答
1

接口/委托/组合的想法可能是“最干净的”。但是一个可以接受且可以说更简单的替代方法是使用静态方法创建一个实用程序类。

public static moveWindowToMagicPositionOnScreen(Window window) {
  // calculate new x and y
  window.setLocation(x, y);  // or perhaps setBounds()...
}

在实践中,我可能会将计算逻辑放入另一种方法computeMagicPositionOnScreen()中。如果有意义(可能没有),这个静态实用程序类实际上可能是一个“真实的”(非静态)类,比如 MagicPositionCalculator,它可能有多个实例,比如每个屏幕一个,一个用于非常大的屏幕,一个用于高级用户等...

于 2012-06-30T06:16:00.090 回答
0

试试这个,

我认为您想应用DRY (Don't Repeat Yourself)设计原则和部分LSP (Liskov substitution Principle),如果您希望将某些方法存储在一个类中,然后从其他两个类中使用此方法,那么我认为优先组合而不是继承将是一个好主意。因为您将能够使用所需的方法,而无需继承您不想要的方法。

于 2012-06-30T05:42:14.727 回答