3

I have a class which implements an interface, but has a couple of extra methods. I can't edit the interface to add any extra methods and one of the methods of that interface returns a type of the interface itself.

public interface ExampleInterface{
    public ExampleInterface method1();
}

The class has an extra method I wish to use which will print the contents of the class.

public class ExampleInterfaceImpl implements ExampleInterface {
    public ExampleInterface method1() {
        //method code
    }
    public void print() {
        //print method code
    }
}

So my question is if i have an object of type ExampleInterface, i.e. what is returned by method1(), and I then want to print it using print(), how can that be done seeing that print() is in ExampleInterfaceImpl so can't be called on an object of type ExampleInterface.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
O Coulson
  • 33
  • 4
  • please write your question more precise – Kitesurfer Oct 31 '15 at 18:48
  • You can attempt to cast or use `instanceof`, otherwise you can't, that's just what interfaces do. – Dave Newton Oct 31 '15 at 18:49
  • If you know it's actually an `ExampleInterfaceImpl`, you can cast it to that type and use the method. But this smells of bad design. You probably should implement `toString()` properly instead of `print()`, and then you'll be able to use that to print the object without casting. – RealSkeptic Oct 31 '15 at 18:49
  • Very simple, you can't invoke a method on a reference whose type doesn't have it's definition. That being said, you can cast your reference to the implementation class. – ares Oct 31 '15 at 18:50
  • 1
    @RealSkeptic The problem with overriding `toString()` to provide human-readable-output-only is that you've then eliminated its function as a debugging tool. I'd rather see the class implement a `Humanized` interface or whatever for things like that. – Dave Newton Oct 31 '15 at 18:50
  • 1
    @DaveNewton `toString` is intended to be a human-readable summary of the class as per its documentation. Debugging is only its secondary usage. – RealSkeptic Oct 31 '15 at 18:56
  • @RealSkeptic My issue with that is that it's used for *any* string representation, e.g., in a log file. Unless you include `super` you lose something very important, not to mention that there may be multiple ways for an instance to be presented in human-readable views. IMO that kind of thing belongs in a presentation layer artifact; you get a lot more versatility. YMMV. – Dave Newton Oct 31 '15 at 18:58
  • @RealSkeptic and @Dave Newton I think both of your answers are correct but it depends on the use case. Especially in this program, what the print method is going to print. Is it instance related details, as eplained in Josh Bloch or something graphical representation. so if it is 1st case I think `toString` is the best choice else `print` method will be. – rajuGT Oct 31 '15 at 19:10

7 Answers7

1

Check if the ExampleInterface object is an instanceof ExampleInterfaceImpl. Then you can cast it to that and call the method -- ((ExampleInterfaceImpl)object).print();.

mvd
  • 2,596
  • 2
  • 33
  • 47
1
public void maybePrint(ExampleInterface obj) {
    if (obj instanceof ExampleInterfaceImpl) {
        ((ExampleInterfaceImpl)obj).print();
    }
}

This works for specific implementing classes, but not if you have several different implementations that may or may not implement the print() method (in that case, you should create a subinterface with the print() method, and implement that in all the applicable classes).

It would also be possible to use reflection to check whether the object's class has a print() method, but that's not very elegant, nor recommended.

Snild Dolkow
  • 6,669
  • 3
  • 20
  • 32
1

If you really cannot modify the interface, you'll have to resort to runttime type checking and casting:

if (myObject instanceof ExampleInterfaceImpl) {
    ((ExampleInterfaceImpl) myObject).print();
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

If you can't change the interface, I suggest you add one which you can.

interface MyExampleInterface extends ExampleInterface {
    MyExampleInterface method1();
    void print();
}

class MyExampleInterfaceImpl implements MyExampleInterface {

// later
MyExampleInterface mei = new MyExampleInterfaceImpl();
mei.method1().print();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

Firstly from comments @RealSkeptic, implementing toString method to your problem is right. If not

Better design would be to create an another interface which can be Printable like

public interface Printable {
    void print();
}

and implement all the classes which can be printable, in your case it is ExampleInterfaceImpl and check the objects type like shown below

if(object instanceof Printable) {
    Printable object = (Printable) object; //this can be ExampleIntefaceImpl object
    object.print(); //is valid
}
rajuGT
  • 6,224
  • 2
  • 26
  • 44
1

If object is stored in interface reference you need to cast that reference to concrete class.

      ExampleInterface exampleInterface = new ExampleInterfaceImpl();

    ((ExampleInterfaceImpl)exampleInterface).print();
Sheebu PJ
  • 31
  • 3
1

So my question is if i have an object of type ExampleInterface, i.e. what is returned by method1(),

you can create the object of class MyExampleInterfaceImpl by referencing type of interface ExampleInterface

ExampleInterface mei = new MyExampleInterfaceImpl();

when you invoke method1() i.e, mei.method(); then it simply call the method from your concrete class which has implemented the interface ExampleInterface

how can that be done seeing that print() is in

Simple do explicit cast the refer variable of ExampleInterface into MyExampleInterfaceImpl() then invoke method print()

 ((ExampleInterfaceImpl)mei).print();

more on explicit casting

Community
  • 1
  • 1
Roushan
  • 4,074
  • 3
  • 21
  • 38