Let's say I have the following interface:
public interface Numeric
{
public Numeric addition(Numeric x,Numeric y);
}
And the following class:
public class Complex implements Numeric
{
private int real;
private int img;
public Complex(int real, int img){
this.real = real;
this.img = img;
}
public Numeric addition(Numeric x, Numeric y){
if (x instanceof Complex && y instanceof Complex){
Complex n1 = (Complex)x;
Complex n2 = (Complex)y;
return new Complex(n1.getReal() + n1.getReal(), n2.getImg() +
n2.getImg());
} throw new UnsupportedOperationException();
}
public int getReal(){
return real;
}
public int getImg(){
return img;
}
}
I have a couple questions:
The addition method has the return type Numeric, and it's arguments are Numeric. x and y are then verified if they are of type Complex. But how can I pass Complex arguments, when in the definition the arguments are of type Numeric? The same when I return. I return a Complex object, not Numeric. What is the correlation and logic behind this.
If x and y are Complex, because I checked in the if, why do I need to cast x and y to new 2 objects? What is the point of casting, if they are already Complex.
And why the if doesn't work without the throw? What does UnsupportedOperationException
is, and why is it mandatory?
As Complex
implements Numeric
, any Complex
object can be used wherever Numeric
is expected.
Every Numeric
object is not Complex
. There can be another class Real
where Real implements Numeric
. In this case, a Numeric
variable can be referencing a Real
object and you cannot substitute a Real
object with Complex
. So, you need to cast the object.
As return type of method addition
is Numeric
, your code MUST be returning an object of type Numeric
. In case you remove throw statement and if condition is evaluated to false, method will not return anything and compiler will complain.