Requiring an argument extends a specific class AND implements a specific interface

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 anything I can replace ' ? 'by allowing me to pass either' A 'or' B '? If I dropped ' x ' to java.awt.Component and saved it to ' c ' and I and saved it to ' I ', I lost the advantage of strong typing.

Do I need to declare

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

and name it " m(a, a) " or " m(b, b) ", where

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

I can not create

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

and pass it on because neither A nor B is c .

By the way, can this be done in Scala?

EDIT: The actual problem I'm trying to solve is that I have two classes: one that extends JInternalFrame and the other that extends JPanel . Both are abstract and provide some common functions for the widgets displayed in them (JTables, where the user can edit lines, delete lines, etc.). The code for editing and deleting lines is always the same, regardless of the display of the displayed types of objects. I have several methods that allow the user to click a row, select "Delete" from the pop-up menu and, for example, ask for confirmation, deletes the selected row and the database object. Sometimes I need a subcomponent of the frame, and sometimes I need a subcomponent of the panel. I created a delegate class for common functionality and an instance variable in each of the abstract classes of this delegate type. The derived classes JInternalFrame and JPanel then simply transfer the actual implementations to the delegate. The delegate class, in turn, needs a pointer to the owner class for callbacks to get the selected row of the table, etc., And a pointer to the " Component " character of each parent for the JOptionPane confirmation dialogs.

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

If I rewrote this in Scala, I would probably do something with traits instead of creating a delegate class. Traits could β€œadd” delete functionality to a specific JInternalFrame class, for example.

Thanks for the tips.

+4
source share
3 answers

Common for salvation!

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

This is not the best way to do something, but in your case it works. You must split your method into two, one for the behavior of I , and the other for the behavior of Component .

+14
source

This is ugly, but you can use generics and restrict the method parameter to extend the class and implement the interface. Here is 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(); dm(impl); } } 

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


[Edit Rahul G ]

Scala path 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 dm(impl) } } 
+11
source

In this case, if you want to do what you are describing, it probably makes sense to create a class C that implements common functions between A and B , from which both A and B can spread. That way, you can simply pass the class C as an argument to the Dm method.

Not knowing the exact classes, it is difficult to make this call finally. I just base it on the function you are trying to create. Since the Dm method, apparently, should be able to work on any of them, they should have something in common.

+4
source

All Articles