Tim
Tim

Reputation: 1074

Class Inheritance and Casting

So I was given this code in a folder of bits and pieces that were to be for a project which has since halted development. However, being new to Java there are several questions I have (and I'm aware the code does not compile, but that works into one of my questions).

interface Executable { 
   public int execute (Object o); 
} 

public class Biv implements Executable { 

   public int execute (String s) { 
     System.out.println (s); 
     return s.length(); 
   } 

   public static void main (String[] args) { 
     Executable e = new Biv(); 
     System.out.println( 
         e.execute ("Hello World!")); 
   }


}

1) My first question is to do with the variable e. It is declared with the Executable object type, however I don't understand why it can then be instantiated with a new Biv object. What is going on here, what does it mean?

2) The error is in the execute method within the Biv class. This seems to be because it expects an object rather than a String. However, can you not replace a Object with a String because String is a subclass of Object? I could understand if you replaced String with Object it would have an error (I think) but not how it is currently done.

Upvotes: 2

Views: 234

Answers (6)

xelamitchell
xelamitchell

Reputation: 522

The Object class implements a toString() method so no casting is necessary. Change Biv to receive an Object rather than a String and in the method call the Object's toString() first and then get the length of the string:

interface Executable { 
   public int execute (Object o); 
} 

public class Biv implements Executable { 

   public int execute (Object s) { 
      System.out.println (s); 
      return s.toString().length(); 
   } 

   public static void main (String[] args) { 
      Executable e = new Biv(); 
      System.out.println( 
          e.execute ("Hello World!")); 
   }

}

However, it is generally bad practice to implement the Command Design Pattern with Object in order to have a method which accepts several types of possible parameters. It would be best to encapsulate parameters behind a Parameter interface.

Upvotes: 0

WW.
WW.

Reputation: 24311

First let's consider this line:

public class Biv implements Executable

implements Executable indicates that the class Biv can take the role of an Executable. Or to put it another way, Biv has an implementation of all the methods in Executable.

This explains why later you can do this:

Executable e = new Biv();

I have a variable of type Executable and on this occasion I'm going to use the Biv implementation of that. If Biv implements the Executable interface (and it declares that it does in your example) then this is ok.

Now let us get to where things start to go wrong with this example. The interface in executable includes this method declartion:

public int execute (Object o);

This says, you can call execute and pass in absolutely any Object you like. But can you pass any object you like to the execute method in Biz? No, you can only pass a String. So Biz is not meeting the interface in full.

[The circle ellipse problem] migth be good further reading.1

Upvotes: 0

Hudon
Hudon

Reputation: 1674

1) The variable e is declared as an Executable which is the interface that Biv implements. This means that you can instantiate a Biv, but store it as an Executable and pass it around as an Executable. That variable can now only be treated as an Executable. This is Polymorphism.

2) This is because you're trying to override a function and adding an additional restriction to the signature. This violates the Liskov substitution principle. For functions, the principle basically states that you should "promise no less and require no more". What you're doing is "requiring more" by forcing the parameter to be a String when the interface says it can be an Object. Then, to relate this to (1), if your Executable object in main has its execute() method called, it should not restrict you to only pass it a String (because the Executable interface says that execute() can take in an Object).

Upvotes: 1

Bohemian
Bohemian

Reputation: 425378

You are not overriding the method from Executable (which is required), you are overloading it (same name, different parameter type).

Use the @Override annotation, which will help highlight the error:

public class Biv implements Executable { 

   @Override // This will cause an error to be highlighted saying this isn't overriding any method
   public int execute (String s) { 
     System.out.println (s); 
     return s.length(); 
   }
}

Upvotes: 0

amit
amit

Reputation: 178521

I don't understand why it can then be instantiated with a new Biv object

Because Biv implements Executable, so any instance of Biv is also an instance of Executable.

The error is in the execute method within the Biv class

Yes it is, it [Biv] does not implement execute(Object). The method execute(String) is just a different method that happen to have the same name, since they don't have the same signature. Any class that implements the interface Executable must override the method execute(Object).

There is no co-variance of arguments in java for overriding methods, because it will be unsafe. What if you invoked e.execute(new Object())? [where e is referencing a Biv object] Biv will not know what to do with it.

Upvotes: 2

Dave
Dave

Reputation: 5173

What you're looking at is Polymorphism, one of the basic concepts in object-oriented programs. To answer you specific question #2, you need to match the type signature of the method in the interface (it takes an object as the argument) and then cast it to a String. This (casting) is, in Java, a bad practice however and should be avoided when possible.

Upvotes: 0

Related Questions