Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using parameter that implements multiple interfaces pre-generics

Suppose I have these interfaces:

public interface I1 {   void foo(); }  public interface I2 {   void bar(); } 

and the classes:

public class A extends AParent implements I1, I2 {    // code for foo and bar methods here }  public class B extends BParent implements I1, I2 {   // code for foo and bar methods here }  public class C extends CParent implements I1 {   // code for foo method here } 

Now, with generics I can have a method like:

public <T extends I1 & I2> void method(T param) {   param.foo();   param.bar(); } 

and I can call it with both A and B as parameters, but not with C (it doesn't implement I2).

Was there a way of achieving this type of type safety pre generics (java < 1.5).

Consider that A, B and C have different inheritance trees, and it's not really an option to do something like AParent and BParent having a common parent themselves.

I know you could do:

public void method(I1 param) {   param.foo();   ((I2)param).bar(); } 

but then you could also call method(new C()) which doesn't implement I2, so you get into trouble.

So are there any other ways you could have done this?

P.S. : I don't really need to do this, it's mostly out of curiosity that I ask.

like image 457
Andrei Fierbinteanu Avatar asked Jun 24 '10 08:06

Andrei Fierbinteanu


People also ask

Can generics take multiple type parameters?

Multiple parametersYou can also use more than one type parameter in generics in Java, you just need to pass specify another type parameter in the angle brackets separated by comma.

Can you implement multiple interfaces?

A class can implement more than one interface at a time. A class can extend only one class, but implement many interfaces. An interface can extend another interface, in a similar way as a class can extend another class.

What is generics type parameter?

Generic Methods A type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.


2 Answers

Create a third interface I3 extends I1 and I2. Then class A and B both implement I3, and the generic method accepts I3.

That's perhaps the only way to do it.

like image 157
Sripathi Krishnan Avatar answered Oct 05 '22 23:10

Sripathi Krishnan


I don't think above answers are good under design viewpoint. When you make an interface, you want to make sure caller object has responsibility for some actions defined in that interface. So there are two solutions discussing above, and I will tell why those solutions aren't good in design viewpoint.

1. make one interface extends both two interfaces:

public interface IC extends IA,IB {    // empty method here } 

Above code is non-sense. You define a separate interface just to combine other interfaces, and inside there aren't any new methods. You add no value to IC instead of combine two interface IA and IB. And some situations, this way will make your code "little fun" when you cannot find the suitable name for third interface. This situation will lead to some interface name such as IReadableAndWriteable or ISomethingAndSomethingAndAnotherThing

2. type cast inside method:

public void methodA(IA object) {    if (object instance of IB) {      ((IB)(object)).someMethod() } 

This way is nonsense too. Why the input parameter is IA then you must execute some action from interface IB? Under programmer viewpoint, there is no way to know that except from reading your document. That's not good for designing a function for other people use.

True solution:

Above solutions there is another problem in design: You force programmer use one object that has responsibility for two interfaces. What is the problem if programmer doesn't want to do this. They want to use two different concreted class for each different interfaces for easier testing, clean code? They cannot.

You should make two different parameters in your method signature:

public void exampleMethod(IA object1, IB object2) {    object1.someMethod()    object2.someMethod() } 

And for calling above method, you put same parameter inside(if programmer use same object). They also can put different objects too.

public void caller() {    IC object3 = new C(); // C is the class implements both IA and IB    exampleMethod(object3, object3);    IA objectA = new A();    IB objectB = new B();    exampleMethod(objectA, objectB);        } 

Hope this help :)

like image 34
hqt Avatar answered Oct 06 '22 00:10

hqt