Let say there is one superclass and two subclasses.
Why Java doesn't allow this scenario:
B -> A (A is superclass of class B)
C -> A
ObjectC c = (ObjectC)(ObjectA)b;
This way I could map common properties from object b to object c.
With (ObjectA)b you have an expression, if evaluated results in a reference of type ObjectA (ObjectA ab = (ObjectA)b). The actual type of the instantiated object (in memory) does not change, only the handle with you hold it (the reference) changes. You cannot cast that reference to ObjectC, because the underlying object instance (originally b) is of type ObjectB.
Let's say we allowed what you wrote in the question ObjectC c = (ObjectC)(ObjectA)b. If you evaluate that you'd get a reference of type ObjectC to the instantiated object b. Let's say ObjectC has a method called run(), but of course, ObjectB does not have to have a run() method. What would happen when you call c.run()?
If you want to map common properties from object b to object c you have to use their common base-class and put common properties there.
Edited with better explanation.
Related
If I would have a variable a declared by A a and a method m with void m(B b). Is there any way that calling m(a) would work? Or can this never work because a is of type A and b of type B.
If A extends B, it can be passed as argument to that function. If not and A contains values suitable for B you have to create an instance of B and fill it with the required values of the instance of A.
This works if A is a subclass of B
This could work in two scenarios:
When A is a B, i.e. inheritance or interface implementation, or
When A and B are primitive data types, and an implicit conversion exists from A to `B.
Here is an example:
void m(long b) {
...
}
int a = 123;
m(a); // This compiles and runs correctly
This can be possible when A is a subclass of B or we can say A extends B,
this is known as inheritance in programming language, in this A will be a child of the class B and inherit all its properties
you can check it from the link below
https://www.tutorialspoint.com/java/java_inheritance.htm
Let us consider we have two classes A and B. B is a sub class for A because B extends A. If We create an instance of A Class and assign that in to a A type will contains all the properties of A. Similarly when I create an Instance of B and assign it to B type will get all the properties of B along with properties of A because it is inheriting from A. According to above lines instance of A contains properties a few as compared to properties contains to instance B. That means Instance of B is Bigger than Instance of A as casting should be explicit when narrowing implicit when widening. According to my theory Instance of B is bigger we are trying to store it in A type we need conversion.
A a1=new (A)B();
The above conversion is taking place implicitly. But my question is how it is implicit, Instance of B is bigger we are trying to convert that to small type which is A. How this is possible???
Answer me with examples thank you in advance.
You are thinking in terms of object size, but in Java, non primitive types are never contained, only referred to. Thus, your code is casting the result of new B(), which is of type "reference to B", to type " reference to A". Since all references are the same size, no data is lost in the cast.
So, I really don't understand your question. I just think you are confused about what happens to the class B members when a upcast to his super class is made. In that case, you ended up with a instance of A wich means that Object type is A and non of B stored data will remain.
In Java, with
B b = new B();
A a = b;
one defines references b and a. Under the hood, references are implemented with pointers, and thus, all references are the same size. Of course, an instance of a B might indeed require more memory than an instance of A (I take it, this is what you mean by "bigger").
By the way, in C++ this is not the case.
B b();
does define an object, not a reference, and therefore
A a = b;
in C++ is indeed not allowed.
Think about this:
class Animal{
public void eat(){}
}
class Monkey extends Animal{
public void climbTree(){}
}
I can now do this:
Animal someAnimal = new Monkey(); //This is ok. (Create a Monkey and identify is as an Animal)
someAnimal.eat(); //This is ok too. (All Animal objects can eat)
someAnimal.climbTree(); //Not ok. Java sees someAnimal as a general Animal, not a Monkey yet.
From the above example, someAnimal is a Monkey object which is stored within a variable of higher hierarchy (Animal).
The object itself is perceived as the a more general class (The Animal class) and I don't think an implicit casting is done here since all Monkeys are already Animals (but not the other way round).
Explicit casting can be done when you want to let the compiler knows that the object actually belongs to a more specific class. For example:
((Monkey)someAnimal).climbTree(); //This is ok. Inform Java someAnimal is actually a Monkey which knows how to climb.
Example :
Class Employee {
private String name;
private double Salary;
//getter & setter
//mutators to increase salary etc;
}
class Manager extends Employee {
private double bonus;
//inherits methods from superclass
// sub class specific methods
}
Employee e = new Manager(); //is fine as manager is also an Employee...
The prefixes super and sub come from the language of sets used in theoretical computer science and mathematics. The set of all employees contains the set of all managers, and thus is said to be a superset of the set of managers. Or, to put it another way, the set of all managers is a subset of the set of all employees.
~ From core java series
hope this helps...
The cast isn't actually implicit like you're saying. What is actually happening is this:
B b1 = new B();
A a1 = (A)b;
The (A) is an explicit cast, what's more important is to stop considering the size of things in the sense that the size of B is different from the size of A. This can be an implicit assignment because B IS-A A, so using A as an interface for B is completely safe, because we know that B has at least the same members as defined by A.
So the perfectly safe (and not erroneous) method of doing this is simple:
A a1 = new B();
Done!
If I have a
class A{ }
class B extends A{ }
and I instantiate a reference variable "var"
A var = new B();
Is "var" then considered to be instantiated as a "B" Object? Where A is the variable reference type and not the Object instantiated for "var".
The object type is still B no matter how you refer to it. That is, the code var.getClass() would return B instead of A, therefore the class of "var" is B.
You could also say that "var" is an instance of A and the code boolean isA = (var instanceof A) would return true, but var.getClass() would not return A.
var is a reference of type A. It points to an object of type B. However, it only knows about the methods that are exposed in A. So, if class B defines a method not present in A, you won't be able to call them from the var reference.
Yes it is going to be successfully casted to A, but you are not going to be able to access any B specific properties from A . See Polymorphism
A and B are both classes. A class is a blueprint, and an object is an instantiation of a class.
However, a variable neither is an object nor holds an object. A variable only holds the location of an object. Therefore, object variables (i.e. non-primitive variables) are called reference variables in Java.
In this specific case, we would say that the variable var is of type A but references an object of type B. Even though var references a B object, it can only access the methods defined in parent A because it is of type A.
A var = new B();
This is a typical example of upcasting in Java.
RHS indicates that object of type B is instantiated in the memory by its default no-args constructor. But you need a reference variable to point to the memory. So in LHS "A var" , var is the reference variable of type A . Since in Java, runtime polymorphism or Dynamic method dispatch is allowed in which call to the overridden method is resolved at runtime rather than compile time and the overridden method is called through the reference variable of the superclass.
So in short. Object of B is instantiated and for achieving runtime polymorphism, it is reference variable of type A.
Hope this understanding will help in discovering your answer.
I have superclass A, which is extended by subclasses B1 and B2. Then, I have five subclasses (C1, C2, C3, C4, C5) that extend either B1 or B2.
I am trying to make an array containing one of each of these five subclasses.
These objects are all instantiated as instances of type A.
ClassA[] objects = new ClassA[5];
I attempt to reassign each of the objects to one of the subclasses:
objects[0] = new ClassC1;
objects[1] = new ClassC2; // etc...
At this point, any methods that existed in Class A work fine, but methods defined in B1/B2 or the other subclasses are not found:
objects[0].MethodFromC1(); // returns a "symbol not found" error
The instanceof keyword indicates that objects[0] is an instance of classes A, B1/B2, and C1.
What can I do to maintain my array of class objects (to loop through and perform operations), while getting my code to recognize the methods of the subclasses?
If you are doing a lot of instanceof and conditional logic based on class, you are completely missing out on the benefits of an object-oriented language. Just stick to C.
You should have some method do(), for example, that is abstract in ClassA but implemented in ClassB and ClassC. Then you iterate over the array and call do() on every object in there. The polymorphic call will result in the right do()'s being called.
Hope that helps.
Elements in the objects array don't know anything about ClassC1 since they're only guaranteed to be members of ClassA.
For instance, if you have a class hierarchy of Animal and subclass Cat and its subclass Lion, you're trying to call the Animal.maimSafarigoer() method. Animals in general don't know anything about safarigoers, only Lions know how to do that.
Use the instanceof operator to check if you're operating on a particular subtype.
(Sorry for the gruesome analogy. :-) )
You're trying to implement variants in Java. This subject has long been one of the things I hate the most about this language.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
I have listed about 8 suboptimal ways to do variants there.
You can use the instanceof keyword in the if statement and cast the object to the desired type. For example,
for (ClassA obj : objects) {
// do something common...
if (obj instanceof ClassC1) {
ClassC1 c1Obj = (ClassC1) obj;
c1Obj.MethodFromC1();
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java inheritance - please explain
I'm learning Java and I have two questions:
What is the difference between:
A x = new A();
and
A x = new B();
Considering that:
class A
class B extends A
What's the difference between:
A x = new B();
(A)x.run_function();
Let's say that both A and B have the function run_function, which one will be executed ?
The most important difference is between the static and dynamic types of objects and references to objects.
Say B extends A and C extends B.
The dynamic type of an object (the type used in the new) is its actual runtime type: it defines the actual methods that are present for an object.
The static type of an object reference (a variable) is a compile-time type: it defines, or rather declares, which methods can be called on the object the variable references.
The static type of a variable should always be of the same type or a supertype of the dynamic type of the object it references.
So in our example, a variable with static type A can reference objects with dynamic types A, B and C.
A variable with static type B can reference objects with dynamic types B and C.
A variable with static type C can only reference objects with dynamic type C.
Finally, calling a method on an object reference is a subtle and complex interaction between static and dynamic types. (Read the Java Language Spec on method invocation if you don't believe me.)
If both A and B implement a method f() for example, and the static type is A and the dynamic type involved is C for a method invocation, then B.f() will be invoked:
B extends A, C extends B
public A.f() {}
public B.f() {}
A x = new C(); // static type A, dynamic type C
x.f(); // B.f() invoked
Simplifying greatly: first the static types of both receiver (type A) and arguments (no args) are used to decide the best-matching (most specific) method signature for that particular invocation, and this is done at compile-time. Here, this is clearly A.f().
Then, in a second step at runtime, the dynamic type is used to locate the actual implementation of our method signature. We start with type C, but we don't find an implementation of f(), so we move up to B, and there we have a method B.f() that matches the signature of A.f(). So B.f() is invoked.
In our example we say that method B.f() overrides method A.f(). The mechanism of overriding methods in a type hierarchy is called subtype polymorphism.
1. In
A x = new A();
x is an instantiation of A and of type A.
whereas in
A x = new B();
x is an instantiation of B and of type A.
2. The important thing to note here is that (in the second case) if you call x.someMethod(), the method of B will be called, not the method of A (this is called dynamic binding, as opposed to static binding). Furthermore, casting changes only the type, so
A x = new B();
((A)x).run_function(); // Need extra parenthesis!
will still call B's method.
As I said above, you need to include those extra parenthesis since
(A)x.run_function();
is equivalent to
(A)(x.run_function());
Case 1:
You will see difference when you have a method in B which is NOT in A.
When you try to call that method using reference 'x' it won't be visible.
Case 2:
All method calls will be based on object type not reference type due to polymorphism (except static methods)
A x = new B();
In this case B class run_function will be executed.
A x = new A();
In this case A class run_function will be executed.
Furthermore with:
A x = new B()
You will not be able to execute methods that are defined in B and that are not defined in A. However as indicated previously because of polymorphism in Java if you do execute any methods and B' has overridden these methods then it will use B's implementation.
1.What is the difference between: A x = new A();and A x = new B();
The difference is that in the first case, you are instantiating a class of type A. So you will only be able to call methods defined in A. IN the second case, if the same name method exists in both A and B, then the B implementation will be invoked at runtime.
However, in the second case, using reflection, it will also be possible to invoke methods that are defined in Class B and not in Class A.
A x = new B();
(A)x.run_function();Let's say that both A and B have
the function run_function, which one will be executed ?
Remember - Overriding is decided at runtime whereas overloading is decided at compile time.
So the method in class B will be invoked at runtime based on Dynamic Binding.
There is no real difference. Actually for the second case A olds a B object, but B is an A so thats no problem. B in this case behaves like A.
It will call B's run_function()