需要参数扩展特定类并实现特定接口

发布于 2024-09-16 18:11:06 字数 1739 浏览 4 评论 0 原文

我有两个 Java 类层次结构,它们共享一个共同的祖先并实现一个共同的接口。我需要将指向其中一个事物的指针传递给另一个类中的方法。

interface I { ... }

class A extends java.awt.Component implements I { ... }
class B extends java.awt.Component implements I { ... }

class D {
  Component c;
  I i;
  void m(? x) {
    c = (Component) x;
    i = (I) x;
  }
}

有什么可以替换“”的东西,让我可以传入“A”或“B”吗?如果我将 'x' 转换为 java.awt.Component 并将其存储在 'c' 和 I 并将其存储在 'i' 中,我失去了强类型的好处。

我是否需要

class D {
  void m(java.awt.Component c, I i) { ... }
}

使用 'm(a, a)' 或 'm(b, b)' 声明并调用它,因为

A a = new A();
B b = new B();

我无法创建

abstract class C extends java.awt.Component implements I {...}

并传递它,因为AB 都不是 C

顺便说一句,这可以在 Scala 中完成吗?

编辑:我试图解决的实际问题是我有两个类,一个扩展JInternalFrame,另一个扩展JPanel。两者都是抽象的,并为其中显示的小部件提供一些通用功能(用户可以在其中编辑行、删除行等的 JTable)。无论显示的基础对象类型如何,编辑和删除行的代码始终相同。例如,我有几种方法允许用户单击一行,从弹出菜单中选择“删除”,并在要求确认后删除选定的行和数据库对象。有时我需要一个框架子组件,有时需要一个面板子组件。我为公共功能创建了一个委托类,并在该委托类型的每个抽象类中创建了一个实例变量。然后,JInternalFrameJPanel 派生类将实际实现推迟到委托。反过来,委托类需要一个指向“所有者”类的指针以进行回调以获取选定的表行等,以及一个指向 Component 的每个父级的性质的指针。 code>JOptionPane 确认对话框。

使用 Java 泛型方法效果非常好。委托类现在被定义为 和每个所有者抽象类都实现 DelegateContainer(回调方法在其中声明)。

如果我要在 Scala 中重写它,我可能会使用特征做一些事情,而不是创建委托类。例如,这些特征可以将删除功能“添加”到 JInternalFrame 派生的具体类中。

感谢您的及时回复。

I have two Java class hierarchies that share a common ancestor and implement a common interface. I need to pass a pointer to one of these things to a method in another class.

interface I { ... }

class A extends java.awt.Component implements I { ... }
class B extends java.awt.Component implements I { ... }

class D {
  Component c;
  I i;
  void m(? x) {
    c = (Component) x;
    i = (I) x;
  }
}

Is there something I can replace the '?' with that will allow me pass in either an 'A' or a 'B'? If I cast 'x' to a java.awt.Component and store it in 'c' and to an I and store it in 'i', I lose the benefit of strong typing.

Do I need to declare

class D {
  void m(java.awt.Component c, I i) { ... }
}

and call it with 'm(a, a)' or 'm(b, b)' where

A a = new A();
B b = new B();

I cannot create an

abstract class C extends java.awt.Component implements I {...}

and pass that in because neither A nor B is a C.

BTW, can this be done in Scala?

EDIT: The actual problem that I am trying to solve is that I have two classes, one that extends JInternalFrame and another that extends JPanel. Both are abstract and provide some common functionality for widgets displayed in them (JTables where the user can edit rows, delete rows, etc). The code for editing and deleting rows is always the same, regardless of the underlying object types being displayed. I have several methods that allow the user to click a row, select 'Delete' from a popup menu, and, after asking for confirmation, deletes the selected row and database object, for example. Sometimes I need a frame subcomponent and at other times a panel subcomponent. I have created a delegate class for the common functionality and an instance variable in each of the abstract classes of that delegate type. The JInternalFrame and JPanel derived classes then just defer the actual implementations to the delegate. The delegate class, in turn, needs a pointer to the "owner" class for callbacks to get the selected table row, etc., and a pointer to the "Component" nature of each parent for the JOptionPane confirmation dialogs.

Using the Java generics approach has worked very well. The delegate class is now defined as a generic class on <T extends Component & DelegateContainer and each of the owner abstract classes implements DelegateContainer (where the callback methods are declared).

If I were going to rewrite this in Scala, I would probably do something with traits instead of creating a delegate class. The traits could "add" the delete functionality to the JInternalFrame derived concrete class, for example.

Thanks for the prompt replies.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

大姐,你呐 2024-09-23 18:11:06

泛型来救援!

public class Test {
    public static void main(String... args){
        new D().m(new A());
        new D().m(new B());
    }
}

interface I {  }

class A extends java.awt.Component implements I {}
class B extends java.awt.Component implements I {}

class D {
  Component c;
  I i;
  <T extends java.awt.Component & I> void m(T x) {
    c = x;
    i = x;
  }
}

这实际上并不是最好的做事方式,但就你而言它是有效的。您确实应该将方法一分为二,一个用于 I 行为,另一个用于 Component 行为。

Generics to the rescue !

public class Test {
    public static void main(String... args){
        new D().m(new A());
        new D().m(new B());
    }
}

interface I {  }

class A extends java.awt.Component implements I {}
class B extends java.awt.Component implements I {}

class D {
  Component c;
  I i;
  <T extends java.awt.Component & I> void m(T x) {
    c = x;
    i = x;
  }
}

It's not really the best way to do things but in your case it works. You should really split your method in two, one for the I behavior and another for the Component behavior.

孤独岁月 2024-09-23 18:11:06

它很丑陋,但是您可以使用泛型并限制方法参数来扩展类并实现接口。这是一个完整的示例:

interface Foo {}

class Bar {}

class Impl extends Bar implements Foo {}

class D {

    private Foo foo;
    private Bar bar;

    <T extends Bar & Foo> void m(T t) {
        foo = t;
    }
}

public class Test {
    public static void main(String[] args) {
        Impl impl = new Impl();
        D d = new D();
        d.m(impl);
    }
}

恐怕我不知道这如何适合 Scala。


[由 Rahul G 编辑]

Scala 方式是相同的。只是语法不同。

trait Foo
class Bar
class Impl extends Bar with Foo

class D {
  private var foo: Foo = _
  private var bar: Bar = _

  def m[A <: Bar with Foo](a: A) {
    foo = a
    bar = a
  }
}

object Main {
  def main(args: Array[String]) {
    val impl = new Impl
    val d = new D
    d.m(impl)
  }
}

It's ugly, but you can use generics and constrain the method parameter to extend the class and implement the interface. Here's a complete example:

interface Foo {}

class Bar {}

class Impl extends Bar implements Foo {}

class D {

    private Foo foo;
    private Bar bar;

    <T extends Bar & Foo> void m(T t) {
        foo = t;
    }
}

public class Test {
    public static void main(String[] args) {
        Impl impl = new Impl();
        D d = new D();
        d.m(impl);
    }
}

I don't know how this would fit into Scala, I'm afraid.


[ Edit by Rahul G ]

Scala way is the same. Just the syntax is different.

trait Foo
class Bar
class Impl extends Bar with Foo

class D {
  private var foo: Foo = _
  private var bar: Bar = _

  def m[A <: Bar with Foo](a: A) {
    foo = a
    bar = a
  }
}

object Main {
  def main(args: Array[String]) {
    val impl = new Impl
    val d = new D
    d.m(impl)
  }
}
烛影斜 2024-09-23 18:11:06

在这种情况下,如果您想按照您所描述的方式进行操作,那么创建一个类 C 来实现 AB 之间的通用功能可能是有意义的AB 都可以从中扩展。这样,您只需将类 C 作为参数传递给 Dm 方法即可。

如果不知道确切的类,就很难做出明确的决定。我只是将其基于您尝试创建的功能。由于 Dm 方法显然需要能够对任一方法进行操作,因此它们必须有一些共同点。

In this case, if you want to do as you describe, it probably makes sense to create a class C that implements the common functionality between A and B from which both A and B can extend. This way, you can just pass class C as the argument to the D.m method.

Without knowing the exact classes, it's hard to make this call definitively. I'm just basing it on the function that you're trying to create. Since the D.m method apparently needs to be able to operate on either, there must be something in common about them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文