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

Ral*_*lph 4 java scala interface multiple-inheritance

我有两个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;
  }
}
Run Code Online (Sandbox Code Playgroud)

有什么东西我可以替换' ?',这将允许我通过' A'或' B'?如果我将' x'转换为' java.awt.Component并将其存储在' c'并将其I存储在' i'中,我将失去强类型的好处.

我需要申报吗?

class D {
  void m(java.awt.Component c, I i) { ... }
}
Run Code Online (Sandbox Code Playgroud)

并用' m(a, a)'或' m(b, b)' 称之为

A a = new A();
B b = new B();
Run Code Online (Sandbox Code Playgroud)

我不能创造一个

abstract class C extends java.awt.Component implements I {...}
Run Code Online (Sandbox Code Playgroud)

并传递它,因为既不是A也不BC.

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

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

使用Java泛型方法非常有效.委托类现在被定义为泛型类<T extends Component & DelegateContainer,每个所有者抽象类都实现DelegateContainer(声明回调方法).

如果我要在Scala中重写它,我可能会使用traits而不是创建委托类.例如,特征可以将删除功能"添加"到JInternalFrame派生的具体类.

感谢您的快速回复.

Col*_*ert 14

通用的救援!

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这不是真正做事的最佳方式,但在你的情况下它是有效的.你应该把你的方法分成两个,一个用于I行为,另一个用于Component行为.


Jon*_*eet 11

它很难看,但你可以使用泛型并约束方法参数来扩展类并实现接口.这是一个完整的例子:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道这会如何适应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)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不知道你可以编辑Jon Skeet的帖子.认为他们是不可改变的或类似的...... :-) (2认同)