Method compiles and works with wrong type of variable passed

Mak :

So here is part of code that I'm testing:

interface sample
{
    Vector Sum(Vector vec);
    Vector Subtraction(Vector vec);
    int Product(Vector vec);
    boolean Compare(Vector vec);
    String ToString();
}

abstract class Vector implements sample
{       
     int[] coordinates; 
     public Vector (int[] coordinates)
     {
         this.coordinates=coordinates;
     }
}

abstract Vector resVec();

public boolean Compare(Vector vec)
{
    if (this.coordinates.length == vec.coordinates.length)
    {
        for (int i = 0; i<vec.coordinates.length; i++)
        {
            if (this.coordinates[i] == vec.coordinates[i])
                continue;
            else return false;
        }
    }
    else 
    {
        throw new ArithmeticException("Can't compare vectors of different length");
    }
    return true;
}

And here is classes that I call methods from: 1)

class Vector3D extends Vector
{

public Vector3D(int n1,int n2,int n3) 
{
    super(new int[]{n1,n2,n3});
}
public Vector3D resVec()
{
    Vector3D resVec = new Vector3D(0,0,0);
    return resVec;
}

public boolean Compare(Vector3D vec)
{
    return super.Compare(vec);
}

2)

class VectorND extends Vector
{
    public VectorND(int...n) 
    {       
            super(n);
    }
    public VectorND resVec()
    {
        VectorND resVec = new VectorND();
        return resVec;
    }

    public boolean Compare(VectorND vec)
      {
          return super.Compare(vec);
      }
}

So the problem is that for some reason if I write something like this in main:

public class main {

    public static void main(String[] args) 
    {
        Vector3D B = new Vector3D(1,-3,3);
        VectorND A = new VectorND(1,-3,3);
        System.out.println(A.Compare(B));
    }
}

It perfectly works and returns true while it should've written an exception that VectorND was expected at the call of Compare from A. What could be the problem?

Magnus W :

The problem is that you're not overriding the Compare() method of the base class Vector in VectorND and Vector3D. Instead, you're declaring new methods that take an object of the same type (VectorND or Vector3D) in your subclasses. The original Compare() method of the base class is still available in the subclasses, and it's that method that get's called when you call A.Compare(B).

To make it more clear, you have

Vector{
    public boolean Compare(Vector vec){ ... }
}

class Vector3D extends Vector {
    public boolean Compare(Vector vec){ ... }
    public boolean Compare(Vector3D vec){ ... } 
}

class VectorND extends Vector {
    public boolean Compare(Vector vec){ ... }
    public boolean Compare(VectorND vec){ ... } 
}

So when you call

A.Compare(B)

and there is no Compare(Vector3D) declared in class VectorND, what you're really doing is calling

Vector.Compare(Vector)

since both A and B are derived from the base class Vector.

If you really want to override the Compare method in Vector with the ones in your subclasses, you need to declare them identically in the subclasses (i.e. with the same type of parameter).

And if you really want the method to throw an exception in the specified case, you need to explicitly check the type of the Vector by using the instanceof operator, and throw an exception if it's not the same type.

public class Vector3D extends Vector {
    @Override
    public boolean Compare(Vector vec){
        if( !(vec instanceof Vector3D) )
            throw new IllegalArgumentException("Vector3D can only be compared to Vector3D!");

        // Compare and return true or false
    }
}

The @Override annotation indicates that you intended to override a method in the base class. If there is no matching method in the base class, for example if you try to do

@Override
public boolean Compare(Vector3D vec)

the compiler/IDE will issue an error to notify you that you're not overriding anything (since the Vector class has no Compare(Vector3D vec) method).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=107584&siteId=1