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.
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.
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)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With