I have a base class called class Base and two children classes
class A extends Base
and
class B extends Base
I have a method foo in Base.
Rather than putting the implementation of foo in class A and class B, so that I can do
void foo (Object o)
{
// A's implementation
assert o instanceof A;
}
void foo (Object o)
{
// B's implementation
assert o instanceof B;
}
Is there anyway to put foo in Base, and still still be able to check for the runtime class? I've thought of something like this:
void foo (Object o)
{
// Check that o is instanceof a runtime class
assert o instanceof this.getClass(); // ????
}
Thanks.
You can implement your method like this:
public void foo() {
if (this instanceof A) {
// implementation for A
}
else if (this instanceof B) {
// implementation for B
}
}
But the point of polymorphism is to put the A implementation in A, so that this implementation can use A's private fields to implement the method (same for B, or course).
getClass().isInstance(o)
That said, perhaps you want to constrain the type in a way the compiler can check? Generics can do that:
class Base<T extends Base<B>> {
void foo(T o) { ... }
}
class A extends Base<A> {
#Override void foo(A o) { ... }
}
Then,
new B().foo(new A());
will not compile.
There is class method isAssignableFrom()
getClass().isAssignableFrom(o.getClass())
instanceof will not work since the parameter can not be 'dynamic'.
You could use the isInstance method of Class
void foo (Object o)
{
// Check that o is instanceof a runtime class
assert getClass().isInstance(o);
}
but this has at least one possible problem:
it will result in an AssertionException if this is an instance of a subclass of A and the object is just a direct instance of A!
In Java, you can check the class of an object using the instanceof operator:
object instanceof M
When you have a Class object, it would make sense to write:
object.getClass().isAssignableTo(MyClass.class)
http://www.ralfebert.de/blog/java/isassignablefrom/
Related
Essentially what I want to do is pass a class as a parameter so that I can preform an instanceof comparison.
public class MyClass
{
Object o = something;
public void myMethod(Class c)
{
if(o instanceof c)
{
do something
}
}
}
Where the parameter Class c is any class that I choose to pass in from else where. Essentially I want to be able to pass in any class and make a comparison.
Any help would be appreciated.
Thanks
You can call Class#isInstance(Object obj):
if(c.isInstance(o)) {
Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator.
Just let the method accept Object. In Java all classes extend from Object.
public class MyClass
{
Object o = something;
public void myMethod(Object c)
{
if(o.isInstance(c))
{
do something
}
}
}
Consider the following:
public class Doer {
public static void doStuff(A a) {
System.out.println("a");
}
public static void doStuff(B b) {
System.out.println("b");
}
}
Where B extends A
And a generic class like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
Doer.doStuff(entity);
}
}
If I call this method as follows it prints "a"
new NewClass<B>().doSomething(new B());
How do I get it to print "b" ?
Thanks in advance
Edit: A dirty solution is to change
Doer.doStuff(entity);
to
if(entity instanceof B){
Doer.doStuff((B) entity);
}else {
Doer.doStuff(entity);
}
But I'm looking for a solution that does not use instanceof and so that I don't have to add an extra if (C intance of A) ... to NewClass when I make a new Class extending A
See these questions for answers: Java Generic / Type Dispatch Question, How does Java method dispatch work with Generics and abstract classes?
Basically, you have these options:
define doStuff as an abstract method on A
try the Visitor pattern
if possible, use a language (e.g. Xtend) that supports dynamic dispatch
Java doesn't do dynamic binding based on the argument type. The actual method that is invoked is determined at compile time. So in case of a generic type, the method with Object as the parameter type will be invoked.
You could work around this by checking the type with instanceof, but the puristic way of handling this is to leverage polymorphism and using Double Dispatch. But that is not always an option, since it tightly couples your calling class and your argument class together.
I think that in that case you're forced to actually determine entity's type and cast it, as your function doSomething just infers that entity inherits from A.
Basically you could do:
public void doSomething(T entity) {
if (entity instanceof B) {
Doer.doStuff((B) entity);
}
else {
Doer.doStuff(entity);
}
}
NewClass would have to have two methods also, or you could do something like this:
public class NewClass<T extends A> {
public void doSomething(T entity) {
if(entity instanceof B){
Doer.doStuff((B)entity);
}else if(entity instanceof A){
Doer.doStuff((A)entity);
}
}
}
My understanding is that every class in Java is a child of the Object superclass. Why, therefore, is it my compiler giving me errors for the following code:
public class ClassA {
public ClassA(){}
public String exampleMethod(String str){
//manipulate string
return str;
}
}
public class ClassB {
public ClassB(){}
public String exampleMethod(String str){
//manipulate string
return str;
}
}
public class Manager {
public Manager(){
execute(new ClassA());
execute(new ClassB());
}
public void execute(Object o){
o.exampleMethod("test");
}
}
If ClassA is a child of Object, why can I not call methods from the 'o' variable? I'm aware that I could just put ClassA & ClassB under a superclass, but I want to know why this fails.
Because Object class has not defined exampleMethod method, thus giving you errors. You should at least do a downcasting o ClassA or ClassB class to execute your code:
public void execute(Object o) {
//this makes the code compiles
((ClassA)o).exampleMethod("test");
}
Still, you have to make sure that the o parameter is an ClassA or ClassB instance before doing this downcasting or you could met the ClassCastException exception. You can achieve this by using instanceof:
public void execute(Object o) {
//this makes the code compiles
//and assures that you won't have a ClassCastException
if (o instanceof ClassA) {
((A)o).exampleMethod("test");
}
if (o instanceof ClassB) {
((B)o).exampleMethod("test");
}
}
Still, this is pretty clumsy. Since ClassA and ClassB classes shares a method with the same signature (same name, same parameters, same return type), you can use an interface that has this method and make ClassA and ClassB classes to implement it. For example:
interface IExample {
String exampleMethod(String str);
}
public class ClassA implements IExample {
//current implementation...
}
public class ClassB implements IExample {
//current implementation...
}
Then you can shorten the code in your Manager class to:
public void execute(Object o) {
if (o instanceof IExample) {
((IExample)o).exampleMethod("test");
}
}
Or even better:
public void execute(IExample o) {
o.exampleMethod("test");
}
This way you can pass an instance of ClassA or ClassB to the execute method and it will behave depending on the implementation that each class gave to the exampleMethod.
Actually, in some looser typed languages your approach would work. In Java you will need to modify the execute() method to something like:
public class Manager {
...
public void execute(Object o){
if (o instanceof ClassA) {
((ClassA) o).exampleMethod("test");
} else if (o instanceof ClassB) {
((ClassB) o).exampleMethod("test");
}
}
}
You approach fails because the class Object does not have a method called exampleMethod().
What would happen if you give e.g. Number to the method?
Unless you don't cast your object to A/B. The reference will remain be of Object class and Object class does not contain any method called exampleMethod(String str). Hence you need to cast it to the classes which have implemented the exampleMethod. You cna do something like this:
public void execute(Object o) {
if (o instanceof A) {
((A)o).exampleMethod("test");
}
if (o instanceof B) {
((B)o).exampleMethod("test");
}
}
Suppose I have two classes deriving from a third abstract class:
public abstract class Parent{
public Parent(){
}
}
public class ChildA extends Parent {
public ChildA {
}
}
public class ChildB extends Parent {
public ChildB {
}
}
In C# I could handle casting in a somewhat type safe manner by doing:
ChildA child = obj as ChildA;
Which would make child == null if it wasn't a ChildA type object. If I were to do:
ChildA child = (ChildA)obj;
...in C# this would throw an exception if the type wasn't correct.
So basically, is there a way to to do the first type of casting in Java? Thanks.
I can't think of a way in the language itself, but you can easily emulate it like this:
ChildA child = (obj instanceof ChildA ? (ChildA)obj : null);
In java 8 you can also use stream syntax with Optional:
Object o = new Integer(1);
Optional.ofNullable(o)
.filter(Number.class::isInstance)
.map(Number.class::cast)
.ifPresent(n -> System.out.print("o is a number"));
You can use this method which is compatible with all java types :
public static <T> T safeCast(Object o, Class<T> clazz) {
return clazz != null && clazz.isInstance(o) ? clazz.cast(o) : null;
}
Example :
// A given object obj
Integer i = safeCast(obj, Integer.class);
You can use the instanceof operator.
if(obj instanceof ChildA){
final ChildA child = (ChildA) obj;
}
You can always just check first:
if (child instanceof ChildA) {
ChildA child = (ChildA) child;
// Do stuff.
}
Or just make a quick method:
public ChildA getInstance(Parent p) {
if (child instanceof ChildA) {
return (ChildA) p;
} else {
return null;
}
}
I think a good way to deal with this is to use generic methods, which is a reusable/safe option as in the following example:
#SuppressWarnings("unchecked")
public <E> E coerceTo(Object o, Class<E> target) throws IllegalArgumentException {
if(target.isInstance(o)) return (E)o;
String msg = "expected "+target.getName()+" but was "+o.getClass().getName();
throw new IllegalArgumentException(msg);
}
Note that here, the cast only occurs when safe, and it's correct to add the suppressWarnings annotation.
Here's an example of how to call the method:
Object o = 1;
int a = coerceTo(o, Integer.class);
In modern Java you would use
if (obj instanceof ChildA childa) {
}
which is nearly the same in modern C#
if (animal is Dog dog)
{
// Use dog here
}
Is there a way to find out the name of derived class from a base class instance?
e.g.:
class A{
....
}
class B extends A{
...
}
class c extends A{
...
}
now if a method returns an object of A, can I find out if it is of type B or C?
using either instanceof or Class#getClass()
A returned = getA();
if (returned instanceof B) { .. }
else if (returned instanceof C) { .. }
getClass() would return either of: A.class, B.class, C.class
Inside the if-clause you'd need to downcast - i.e.
((B) returned).doSomethingSpecificToB();
That said, sometimes it is considered that using instanceof or getClass() is a bad practice. You should use polymorphism to try to avoid the need to check for the concrete subclass, but I can't tell you more with the information given.
Have you tried using instanceof
e.g.
Class A aDerived= something.getSomethingDerivedFromClassA();
if (aDerived instanceof B) {
} else if (aDerived instanceof C) {
}
//Use type-casting where necessary in the if-then statement.
Short answer to your question
Is there a way to find out the derived class's name from a base class object?
no, the super-class has no way of telling the name/type of a sub-class.
You have to interrogate the object (which is an instance of a sub-class) and ask if it is an: instanceof a particular sub-class, or call it's getClass() method.
You can do it in the subclass' constructor
class A {
protected String classname;
public A() { this.classname = "A"; }
public String getClassname() { return this.classname; }
}
class B extends A {
public B() {
super();
this.classname = "B";
}
}
So
A a = new A();
a.getClassname(); // returns "A"
B b = new B();
b.getClassname(); // returns "B"
((A)b).getClassname(); // Also returns "B"
Because it is casted into an "A" object, it will call the "A" getClassname() function but will return a value set by the constructor that was the "B" constructor.
Note: Call super(); before setting it
There are 2 ways I can think of
1) One with Using the Java reflection API
2) Other one would be with the instanceOf
Other method can be a Comparing objects to objects, I dont know how it might be, you can try this
Is there a way to find out the name of derived class from a base class instance?
As answered here, you can use this extremely simple approach.
abstract class A {
public final String getName() {
return this.getClass().getName();
}
}
class B extends A { }
class C extends A { }
then simply print the current class name:
B b = new B();
C c = new C();
System.out.println(b.getName());
System.out.println(c.getName());
Output:
com.test.B
com.test.C
There is no need to store additional Strings, check instanceof or override the method in any subclass.
A more modern approach (Java 16+) would be using pattern matching for the instanceof operator. The syntax is pretty simple:
if(x instanceof X xChild){
// use xChild
}
It is both shorter and less error-prone as it combines all the steps of testing the runtime type of the variable(x in the example above), casting it down, and assigning it to a new variable(`xChild in the example above). Read more.
Another example:
public void addUIControl(UIControl control) {
if(control instanceof SelectList sl){
selectList = sl;
}
else if(control instanceof TextBox tb){
textBox = tb;
}
else if(control instanceof Button btn){
button = btn;
}
else {
throw new IllegalArgumentException("Uknown UIControl object has been passed to the SendFormMediator");
}
}