Reputation: 327
I am referencing this duplicate question here:
Check if a Class Object is subclass of another Class Object in Java
I have an abstract parent class named 'Figure' of which I have two subclasses, 'Circle' and 'Rectangle' both of which extend this abstract parent. I am trying to determine if a Figure object is of type Circle or type Rectangle.
My original code was:
public boolean isInstanceOfRectangle(Figure figure)
{
boolean isInstance = figure instanceof Rectangle;
System.out.println("instance of rectangle!");
return isInstance;
}
After studying the linked question above, I have rewritten my code as follows:
public boolean isRectangle()
{
boolean isInstance = Figure.class.isAssignableFrom(Rectangle);
System.out.println("instance of rectangle!");
return isInstance;
}
For some reason this does not work unless I include the following in my main class:
public Class<?> Rectangle;
public Class<?> Circle1;
I'm not sure the significance of including this in my class, if I do not, it seems to require that I include it as a parameter in my method. I am unable to correctly invoke and test this method because I am unsure what parameter to pass into the method when invoked. I'd like to write something like:
public void mouseReleased(MouseEvent e)
{
if ((isRectangle(shape1)))
addRectangle((Rectangle)shape1, e.getComponent().getForeground());
else if ((isCircle(shape1)))
addCircle((Circle) shape1, e.getComponent().getForeground());
}
where 'shape1' is a Figure object that was instantiated as either a circle or a rectangle. Because the parameter is of type Figure, I am unsure how to define the 'isRectangle' method to take a Figure object (the abstract parent) and determine specifically which subclass it is an instance of. Or preferrably to take no parameter and just do the work by using the Figure object to invoke the method. I am a bit confused how to proceed.
*Edit: upon user suggestions, I have rewritten the following which does NOT appear to work because in both cases the output is FALSE.
Figure circleObj = new Circle(Color.BLUE);
System.out.println(isInstanceOfRectangle(circleObj));
System.out.println(isInstanceOfCircle(circleObj));
public static boolean isInstanceOfRectangle(Figure figure)
{
boolean isInstance = figure instanceof Rectangle;
if (isInstance == true)
System.out.println("instance of rectangle!");
else
System.out.println("is NOT a rectangle");
return isInstance;
}
public static boolean isInstanceOfCircle(Figure figure)
{
boolean isInstance = figure instanceof Circle;
if (isInstance == true)
System.out.println("instance of circle!");
else
System.out.println("is NOT a circle");
return isInstance;
}
Upvotes: 5
Views: 7398
Reputation: 179
You can use the .getClas() method to find the subclass
Rectangle aRectangle = new Rectangle();
if (aRectangle.getClass == Rectangle.class){
// Do what you would do if it was a rectangle
System.out.println("you have a rectangle");
}
else{
// The figure is not a rectangle
System.out.println("the figure is not a rectangle");
}
Upvotes: 2
Reputation: 131526
That will always return false
since the Figure
Class
instance is not a subclass of the Rectangle
Class
instance :
boolean isInstance = Figure.class.isAssignableFrom(Rectangle.class);
You want to generally invoke isAssignableFrom()
on the class of a variable which you don't know the runtime type.
It would make more sense :
Figure figure = ...;
boolean isInstance = Rectangle.class.isAssignableFrom(figure.getClass());
That allows to know whether the instance of the class of the figure
variable IS a Rectangle
.
Introducing a method to handle the requirement would make still more sense as it is dynamic and it also allows to handle different class compatibility checks :
public static boolean isInstanceOf(Figure figure, Class<?> clazz){
boolean isInstance = clazz.isAssignableFrom(figure.getClass());
return isInstance;
}
And you could so use it such as :
System.out.println(isInstanceOf(new Rectangle(), Rectangle.class));
System.out.println(isInstanceOf(new Circle(), Rectangle.class));
System.out.println(isInstanceOf(new Figure(), Rectangle.class));
That prints :
true
false
false
And of course all of these will outputtrue
as a Figure
, a Circle
and a Rectangle
are Figure
s :
System.out.println(isInstanceOf(new Rectangle(), Figure.class));
System.out.println(isInstanceOf(new Circle(), Figure.class));
System.out.println(isInstanceOf(new Figure(), Figure.class));
Upvotes: 4
Reputation: 3180
I'm going to chime in here and point out a bug in these methods:
public static boolean isInstanceOfRectangle(Figure figure)
{
//boolean isInstance = figure instanceof Rectangle;
boolean isInstance = figure instanceof Rectangle;
if (isInstance == true)
System.out.println("instance of rectangle!");
else
System.out.println("is NOT a rectangle");
return isInstance;
}
public static boolean isInstanceOfCircle(Figure figure)
{
//boolean isInstance = figure instanceof Rectangle;
boolean isInstance = figure instanceof Rectangle;
if (isInstance == true)
System.out.println("instance of circle!");
else
System.out.println("is NOT a circle");
return isInstance;
}
In the second method, the behaviour you want is for it to check whether or not it is a circle. But instead, you check if it is a rectangle.
Instead of figure instanceof Rectangle
you should be checking figure instanceof Circle
PS. it is acceptable to use instanceof
. Anything else is overkill.
Upvotes: 1
Reputation: 26094
Your original implementation is correct and the simplest one until we get pattern matching in Java.
More detailed explaination:
instanceof
operator can be used to check if an object is an instance of a particular class. This matches your intent.
You can achieve similar functionality with ClassA.isAssignableFrom(ClassB)
. Here, ClassA is superclass and ClassB is a subclass. Note that this function compares two classes (instances of Class<?>
), not an instance against a class.
You can get the class from an instance using getClass
method, and thus, the resulting code will look like:
Rectange.class.isAssignableFrom(figure.getClass())
Your proposed check
Figure.class.isAssignableFrom(Rectangle);
has multiple problems:
Class<?>
instance on the right side, you could use class literal Rectangle.class
, but this checks a trivial fact and is always true.Class<?> Rectangle
, but this variable does not have any relation with Rectangle
class, unless explicitely initialized with class literal Rectangle.class
Upvotes: 1
Reputation: 453
I don’t see much reason to complicate your code with assignable. Your original code works. More than that, checking variable’s class is not a good practice, try to restructure your code. (Check polymorphism, Barbara Liskov principle and Interface segregation principle) And for clarifying things: Figure is not an object since it’s abstract, it’s type. The type is what stands on the left side of variable declaration.
Upvotes: 1