【问题标题】:How to implement code to multiple classes in Java?如何在Java中实现多个类的代码?
【发布时间】:2012-06-30 04:29:53
【问题描述】:

我有 两个 类: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(),将窗口移动到屏幕上用户友好的位置——我知道,这只是一个示例。我希望该方法同时适用于JDialog 和JFrame。使用继承,我必须编写两个类,例如MagicJDialog 和MagicJFrame,每个类都以完全相同的方式实现方法moveWindowToMagicPositionOnScreen()。嗯,这很多余。所以我不想让代码写两次。在某种程度上,我希望 一个 类使用另一个类的代码。

【问题讨论】:

  • 你考虑过构图吗?
  • PS:你应该提供一个你所寻求的例子......
  • 术语: 你不是在“重写”java.awt.Window 的源代码,而是在你的课堂上重写它(假设那里没有什么 final 阻止你这样做)。

标签: java class inheritance


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      public interface Magic {
          void moveWindowToMagicPositionOnScreen();
      }
      

      如果移动窗口的代码一模一样创建一个委托类:

      public class MagicDelegate implements Magic {
      
          public void moveWindowToMagicPositionOnScreen() {
              // TODO implement logic
          };
      }
      

      然后让你的两个类使用MagicDelegate 实现Magic 接口:

      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() 方法。

      【讨论】:

        【解决方案4】:

        试试这个,

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-10
          • 1970-01-01
          • 1970-01-01
          • 2017-11-15
          • 1970-01-01
          • 2015-02-19
          • 2020-07-19
          相关资源
          最近更新 更多