2010-09-01 62 views
4

我有两个共享一个公共祖先并实现一个通用接口的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派生类然后只是将实际实现推迟到委托。反过来,委托类需要一个指向“所有者”类的指针以获取选定表格行等的回调,以及指向JOptionPane确认对话框的每个父项的“Component”性质的指针。

使用Java泛型方法工作得很好。委托类现在定义为<T extends Component & DelegateContainer上的泛型类,每个所有者抽象类实现DelegateContainer(其中声明了回调方法)。

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

感谢您的及时回复。

+1

A和B都是实现我的组件...这需要一个AbstractIComponent ...为什么这不适合你? – Arne 2010-09-01 19:10:59

+0

@Arne:我不相信这会工作,因为'A'和'B'类不是'AbstractIComponent'类型。 – Ralph 2010-09-02 11:44:06

回答

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; 
    } 
} 

这不是真正的最佳做法,但在你的情况下,它的工作原理。你应该真的把你的方法分成两部分,一部分为I行为,另一部分为Component行为。

+0

请参阅上面的**编辑**以澄清问题。顺便说一句,仿制药解决方案工作得很好。谢谢。 – Ralph 2010-09-02 11:45:58

4

在这种情况下,如果你想为你描述的事情,它可能有必要创建一个类C实现AB之间通用的功能从两个AB可以延长。这样,您可以将类C作为参数传递给D.m方法。

如果不知道确切的类别,很难确定这个调用。我只是将它建立在你试图创建的功能上。由于D.m方法显然需要能够在任一方式上操作,所以对它们必须有共同之处。

+0

这对我来说不起作用。类“A”和“B”实际上扩展了其他扩展Component的类。实际上,我正在尝试创建一个新的类“D”,它充当代理来执行“A”和“B”尝试执行的常见操作。我需要将'A'和'B'传递给'D'的构造函数,以便它可以回调到'A'和'B'。 – Ralph 2010-09-01 21:01:34

+0

这非常令人费解。我的直觉说整个安排需要简化。不过,很难说没有细节。 – 2010-09-02 11:42:50

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); 
    } 
} 

我不知道这将如何适合斯卡拉,我害怕。


[由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) 
    } 
} 
+1

+1。顺便说一下,我的评论添加到你的答案。评论框似乎并不适合发布代码。 – missingfaktor 2010-09-01 19:36:23

+2

我不知道你可以编辑Jon Skeet的帖子。以为他们是不可变的或类似的东西...... :-) – 2010-09-01 19:41:28

+0

@Missing Faktor:对我来说很有意义。 – 2010-09-01 19:43:04

相关问题