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

Asked

Viewed 959 times

1

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 in 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 !");
    }
}

Seeking to follow the proposal of programming for an interface and not for 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 variable type (interface), I cannot, 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 shapes I found were by putting the type of variable (class) or keeping the type of variable (interface) but casting the 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 to use a instanceof to check if the variable is of a certain type, but it does not seem to me a good choice to keep putting tests to check if the class supports certain 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?

2 answers

5

An interface is a contract, where both parties, the class it implements and the class it uses, know the "rules" of the contract.

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

All methods that will be public should be on the interface, because the class you will use should know exactly all what she can use, otherwise there is no point in having an interface.

To answer your question, when creating an interface type object, 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 name the class or cast it, as you did in the example.

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

  • Actually I wasn’t thinking about specializing subclasses. I was focused on implementing an interface myself. The idea of specialization emerged as a means of trying to solve a planning problem (or lack of it) in creating the interface.

4


The problem is that you don’t understand what it is to program to interface. I believe that you think it is a rule that you have created and must follow. It is not. It is something to understand why there is this and to do when necessary.

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

Make a cast or something else, is to make a mistake to fix the first mistake made.

Interfaces should be used to segregate responsibilities. You interface program so that what will receive the object can only access what is in that type. It is purposeful that does not allow access to the other members of the specific object. If you used the interface, that code does not know what is not in the interface.

Still want to call didSomething() and be by an interface? There are two possibilities:

  • Create a new interface with this method and then you can declare the variable with the type of interface, access the desired method, and will be programming to the interface. I consider this the most appropriate, but it may not be, in an abstract example like this, anything is possible;
  • Place the method in the existing interface and you can access it. It may not be what you want, but it is a possibility. I don’t know what you want, the names used don’t indicate what it should be.

In fact although it is useful to see how it works, programming for an interface in something simple like this has no practical use at all. It is useful to use this technique when you have complex systems, which will need 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();
    }
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

  • In fact this question is due to the concern that an interface is not well defined in its creation. An example: I may have created an interface and after a while have noticed that it should have one more method. What to do like all those who use my interface ? After all, they would all have to modify their classes. So I thought about this alternative (mistaken) when the ideal (I think) would be to create a new interface with the new methods and leave it to other people to decide whether or not to use the new interface.

  • @Robertocoelho is basically this, even when you are wrong in planning, it is not always easy to solve later.

  • @bigdown further refining the subject: a good practice to correct the error and force the use of the new interface in future versions, would be to use "@Deprecated" in the poorly planned interface...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.