如何确保接口实现扩展特定的类?

4
我有两种类型的编辑器。一种是JTextArea的子类,另一种是JTable的子类(JTextAreaJTable都是JComponent的子类)。 我想让我的两个类TextAreaEditorTableEditor实现接口Editor,该接口只有一个方法public String getText()
我希望客户端代码简单地使用Editor接口。问题在于,所有我的Editor都使用JComponent的方法,例如setEnabled(bool)。由于我的编辑器是一个接口,我无法使其扩展JComponent,因此我必须在调用这些方法时使用实现而不是接口。所以我认为,我可以将Editor简单地作为JComponent的子类,然后将我的类扩展它。但问题在于,像TextAreaEditor这样的类已经扩展了如JTextArea之类的某些类,因此我无法使它们扩展另一个类。
有没有办法确保我的Editor类是JComponent,并且我的具体编辑器类是EditorJComponent的子类?

1
这有点不清楚。你能发一些示例类/实现吗?特别是,为什么Editor必须是一个类不太清楚? - user3458
对我来说,你似乎可以使用抽象类。将Editor作为抽象类扩展JComponent,然后使TextAreaEditor和TableEditor扩展JComponent并实现setEnabled(bool)。 - Asterisk
我尝试用一个新的标题来捕捉我对你问题的理解。这就是你真正想问的吗? - erickson
@Arkadiy 最初它是一个接口。当我需要调用editor.setEnabled(true)时,我遇到了问题,因为setEnabled()是JComponent类的一个方法。@Asterisk 问题在于TextAreaEditor需要扩展JTextArea,因此它不能同时扩展抽象类。@erickson 是的,这对我来说看起来是一个更好的标题。很难措辞。 - gsgx
你可以在编辑器接口中添加 setEnabled 吗? - user3458
6个回答

4
如果您在编辑器接口的子类中公开所关心的JComponent方法,它们将被您的类“回溯”实现。

以下是一些代码来演示这个想法:

interface Editor { 
  String getText(); 
}

interface SwingEditor extends Editor { 
  void setEnabled(bool); // has to match *exactly* the signature from JComponent
}

class TableEditor extends JTable implements SwingEditor {
   // implement your getText(), and anything else you need 
   // no need to implement setEnabled, as it is provided by JTable
}

SwingEditor te = new TableEditor();
te.setEnabled(true); // will call JComponent's method

我假设你确实需要继承,但通常在Swing UI代码中,组合是更好的选择。


3
使用组合优于继承。大多数情况下,继承并不是正确的解决方案,在您的情况下,它可以节省您编写相当多的代码。
让您的TextAreaEditorTableEditor都拥有它们所需的JComponent实例。 将您需要的所有方法添加到接口中,然后将这些调用委托给JComponet
例如:
public class TextAreaEditor implements Editor {
     private final JTextArea textArea = new JTextArea();

     public void setEnabled(bool isEnabled) {
          return textArea.setEnabled(isEnabled);
     }

     //... your own methods plus other methods from JComponent
}

你可能想要变得更加复杂,使用某种依赖注入来实例化JComponent,但这并不是必需的。然而,它可以解决如果所有更改都是需要注入特定的JComponent时必须有两个类的问题。
如果需要更多说明,请告诉我。

2
如果您确实需要将您的Editor类作为JComponent,那么您可以选择在代码中进行强制类型转换并进行文档记录。这不是最优雅的解决方案,但绝对是最简单的方法。
另一种方法是向Editor接口添加一个额外的方法:
public JComponent getComponent();

您的Editor实例可以通过简单地返回this来实现此方法。

后一种方法的好处是,您可以使用所有JComponent方法,而不必在接口中复制它们,并且在2个月内得出结论,即您忘记将其中一个JComponent方法添加到您的接口中。


1
以下设计已经考虑到了这一点:
public class TextAreaEditor extends JTextArea implements Editor {
//provide your implementation of getText()
//setEnabled(bool) doesn't have be implemented as JComponent will provide
}

TextAreaEditor te = new TextAreaEditor();
te.setEnabled(true); // will call JComponent's impl

根据上述代码,您自己的具体实现编辑器(TextAreaEditor)是一个编辑器并且是JComponent的子类。

0

我可能会创建一个新的表格和文本区域类,扩展它们各自的超级类,并实现一个编辑器接口,如下所示

public class JTextAreaEditor extends JTextArea implements Editor {
...
}

然后使用组合来公开Editor接口的方法

    public class JTextAreaEditor extends JTextArea implements Editor {
       private Editor editor;

       public String getValue() {
          return editor.getValue();
       }
       ...
    }

0

我认为你的论点是错误的:对于一个接口(Editor),你不应该关心实现方式。你说所有的Editor实现都需要是JComponent,这只是目前的情况,但它从来不需要成为“Editor”必须满足的“要求”。Editor的设计没有理由强制要求这样做,只要实现符合Editor所要求的(getText())即可。

你所谈论的大多数是“普通”Editor实现的默认基类。再次强调,实现是否选择使用此基类是他们的选择,只要他们符合你的Editor接口即可。

public interface Editor {
    String getText();
}

public abstract class JComponentEditor extends JComponent 
        implements Editor {
    //.....
}

public TextAreaEditor extends JComponentEditor {
    public String getText() {
        // implements TextAreaEditor's version of getText
    }
}

编辑:我可能在OP的问题上有点误解。无论如何,我的答案中的主要论点仍然成立:强制执行“...我的Editor类是JComponent,我的具体编辑器类是Editors和JComponent的子类”是没有意义的。这只是Editor的实现细节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接