Instantiate an object through the interface and access methods not present in it

2

I have the following interface:

interface something {
    void doSomething();
}

And I have a class that implements this interface and adds another method that does not contain the interface:

public class Whatever implements something {

    //Método da interface
    public void doSomething() {
       System.out.println("Do something !");
    }     

    public void didSomething() {
       System.out.println("Did something !");
    }
}

Looking to follow the proposal of programming for an interface rather than an implementation, the code below would be correct:

   public class Test {
       public static void main(String[] arguments) {
          Something s = new Whatever();
          s.doSomething();
       }
   } 

Now, if I want to call the specialized method of class Whatever , from the type of variable (interface), I can not because the method is not found.

   public class Test {
       public static void main(String[] arguments) {
          Something s = new Whatever();
          s.doSomething();
          //Erro, pois não acha o método
          s.didSomething();
       }
   } 

The only two ways I found were by putting the type of variable (class) or keeping the variable type (interface) but casting a method call:

   public class Test {
       public static void main(String[] arguments) {

          //Isso...
          Something s = new Whatever();
          s.doSomething();
          ((Whatever) s).didSomething();

          //Ou isso...
          Whatever w = new Whatever(); 
          w.doSomething();
          w.didSomething();
       }
   } 

1) Is there another way to access this specialized method in the concrete class that implements the interface? I thought I would use instanceof to check if the variable is of a certain type, but it does not seem like a good choice to put tests to check if the class supports a particular method.

2) If it does not exist, what would be the advantage of using classes that have specialized methods but that implement interfaces, since the type of variable would have to be of a concrete class and not of an interface?     

asked by anonymous 26.01.2017 / 00:30

2 answers

3

The problem is that you did not understand what it is to program for interface. I believe you are thinking that it is a rule that you have created and should follow. It is not. It's something to understand why there is and do it when needed.

You must declare a variable as the interface if you just need what is in the interface. If you need what is in the concrete class then you must declare the concrete class.

cast or something else is to make an error to fix the first error committed.

Interfaces should be used to segregate responsibilities. You program to interface so that what will receive the object can only access what is in that type. It is purposely not to let the other members of the particular object access. If you used the interface, that code is unaware of what is not in the interface.

Still want to call didSomething() and be through an interface? You have two possibilities:

  • Create a new interface with this method and there you can declare the variable with the interface type, access the desired method, and you are programming for the interface. I think this is the most appropriate, but it may not be, in an abstract example like this, anything is possible;
  • Place the method on the existing interface and you can access it. It may not be what you want, but it's a possibility. I do not know what you want, the names used do not indicate what it should be.

Actually although it is useful to see the operation program to interface in something simple so it has no practical utility whatsoever. It is useful to use this technique when you have complex systems, which will require maintenance and flexibility to change the implementation without having to change the contract.

interface Something {
    void doSomething();
}

interface Otherthing {
    void doOtherthing();
}

class Whatever implements Something, Otherthing {
    public void doSomething() {
       System.out.println("Do something !");
    }     
    public void doOtherthing() {
       System.out.println("Do otherthing !");
    }
}

class Test {
    public static void main(String[] arguments) {
        Something s = new Whatever();
        s.doSomething();
        Otherthing w = new Whatever(); 
        w.doOtherthing();
    }
}

See running on ideone . And at Coding Ground . Also put it on GitHub for future reference .

    
26.01.2017 / 00:53
4

An interface is a contract, where both parties, the class you implement and the class you use, know the "rules" of the contract.

What's the point of creating a "rule" that is not in the contract, in your case the didSomething method?

All methods that will be public should be in the interface, because the class you will use must know exactly everything what it can use, otherwise there is no sense in having an interface.

By answering your question, when creating an object of the type of an interface, you will only be able to use what is exposed in the interface, the code will not "see" other methods not specified in the interface, unless you instantiate the class by name or cast, as you did in the example.

What you want to do is look more like a specialization of the class with a specific method, which in this case would be an inheritance, not the use of an interface.

    
26.01.2017 / 00:53