Reputation: 23
My code kind of look like this.
class A {
//constructor
}
class B extends A {
//constructor
public void someMethod() {
System.out.println("In B");
}
}
class C extends A {
//constructor
public void someMethod() {
System.out.println("In C");
}
}
public static void main(String args[]){
Object obj = new obj();
B[] classB = new B(){0,1,2,3,4};
C[] classC = new C(){0,1,2,3,4};
Scanner input = new Scanner(System.in);
System.out.print("Enter class: ");
String class = input.next();
System.out.print("Enter index: ");
int index = input.nextInt();
if(class.equals("B") {
// I want to change Object type of obj to B so that I can access methods of B
obj = classB[index];
} else if(class.equals("C") {
// I want to change Object type of obj to C so that I can access methods of C
obj = classC[index];
}
// if user input class B the code below should run method of class B
obj.someMethod();
}
I have searched for something along the lines of permanent casting of object but it was too complicated for me.
Upvotes: 0
Views: 1070
Reputation: 154
Change the line
Object obj = new Object();
in your code to
A obj;
Also correct your class A to:
abstract class A {
//constructor
public abstract void someMethod();
}
and your code will work (as explained by @rzwitserloot).
On the other side, if you don't want to define the method in class A, you must cast your obj to the correct type before you can call the method: leave your code as it is, but replace your line at the end:
obj.someMethod();
with:
if (obj instanceof B) {
((B)obj).someMethod();
}
else if (obj instanceof C) {
((C)obj).someMethod();
}
else {
// throw some error
}
But the best way is to just define an interface (I suggest "ClassNameReporter") with the method someMethod() and let class B and C implement it. Then you can keep your code as it is except changing
Object obj = new Object();
in your code to
ClassNameReporter obj;
Upvotes: 2
Reputation: 102814
You appear to be confusing a variable type and the type of the object it is pointing at.
Given:
class Parent {}
class Child extends Parent {}
In:
Parent p = new Child();
You have exactly 1 instance; its type is Child
; like anything whose type is Child
, it is also of type Parent
, and also of type Object
.
It is confusing to say that 'p is of type Parent'. So don't say it.
This works: p is a variable of type Parent; it is referencing an instance of Child.
And should clarify a thing or two.
p can point at other things. You can write:
Parent p;
p = null;
p = new Child();
p = new Parent();
and the compiler won't complain. Over the lifetime of p, it starts out being illegal to read from it, then referencing nothing (null), then referencing an instance of Child, and finally referencing an instance of Parent. No, you can't 're-define' the p variable to all of a sudden be of type Child, even if it is pointing at an object which so happens to actually be a child. That's a bit like trying to redefine a circle to have corners.
Nevertheless, in:
Parent p = new Child();
p (the variable) is of type Parent, but p (after resolving the reference) is a Child. You can treat it as one:
Child c = (Child) p;
This is a type-checking cast operation: This code can do one of two things:
c = p
, and the cast operation serves solely to make the compiler do it (without the cast, the compiler will refuse to compile this). The point is, nothing is converted, p references an object, and after this statement, c references the exact same object. It's just that you can do more with the c variable now. But it's the same instance.ClassCastException
is thrown.In no case is anything converted, and the cast operation cannot convert anything at all ever, except for primitives (that's a real guns and grandmas situation: int x = (int) v;
looks very similar to String y = (String) z;
but these 2 snippets do completely unrelated things that just happen to look similar.
Upvotes: 3