class A
{
int i=10;
void show()
{
System.out.println("class A");
}
}
class B extends A
{
int i=5;
public void show()
{
System.out.println("class B");
}
}
class M
{
public static void main(String s[])
{
A a=new B();
a.show();
System.out.println(a.i);
}
}
OUTPUT= class B
10
If class A method is overridden by class B method then why not the variable 'i'?
Because variables are not virtual, only methods are.
It is not overwritten, but hidden. In your output you specifically requested the value of a.i, not ((B)a).i.
This is a "feature" of the implementation. In memory, this looks like so:
a:
pointer to class A
int i
b:
pointer to class B
int i (from A)
int i (from B)
When you access i in an instance of B, Java needs to know which variable you mean. It must allocate both since methods from class A will want to access their own field i while methods from B will want their own i (since you chose to create a new field i in B instead of making A.i visible in B). This means there are two i and the standard visibility rules apply: Whichever is closer will win.
Now you say A a=new B(); and that's a bit tricky because it tells Java "treat the result from the right hand side as if it were an instance of A".
When you call a method, Java follows the pointer to the class (first thing in the object in memory). There, it finds a list of methods. Methods overwrite each other, so when it looks for the method show(), it will find the one defined in B. This makes method access fast: You can simply merge all visible methods in the (internal) method list of class B and each call will mean a single access to that list. You don't need to search all classes upwards for a match.
Field access is similar. Java doesn't like searching. So when you say B b = new B();, b.i is obviously from B. But you said A a = new B() telling Java that you prefer to treat the new instance as something of type A. Java, lazy as it is, looks into A, finds a field i, checks that you can see that field and doesn't even bother to look at the real type of a anymore (because that would a) be slow and b) would effectively prevent you from accessing both i fields by casting).
So in the end, this is because Java optimizes the field and method lookup.
Why no field overrides in Java though?
Well, because instance field lookups in Java happen at compile time: Java simply gives you the value of the field at a given offset in object's memory (based on the type information at hand during compilation: in this case a is declared to be of type A).
void foo() {
A a = new B();
int val = a.i; // compiler uses type A to compute the field offset
}
One may ask "Why didn't compiler use type B since it knows that a is in fact an instance of B? Isn't it obvious from the assignment just above?". Of course, in the case above, it's relatively obvious and compiler may try to be smarter and figure it out.
But that's compiler design "rat hole", what if a "trickier" piece of code is encountered, like so:
void foo(A a) {
int val = a.i;
}
If compiler were "smarter", it would become its job to look at all invocations of foo() and see what real type was used, which is an impossible job since compiler can not predict what other crazy things may be passed to foo() by unknown or yet unwritten callers.
It's a design decision by the developers of Java, and is documented in the Java Language Specification.
A method with the same method signature as a method in its parent class overrides the method in its parent class.
A variable with the same name as a variable in its parent class hides the parent's variable.
The difference is that hidden values can be accessed by casting the variable to its parent type, while overridden methods will always execute the child class's method.
As others have noted, in C++ and C#, to get the same override behavior as Java, the methods need to be declared virtual.
a is an instance of A. You call the constructor B(). But it is still a A class.
That is why i equals 10;
The override from the method will be succeded.
Note a class starts not with
public class A()
but with;
public class A { ... }
Tip: You can use setters and getters to make sure of what data-members you use.
Or: You simply can set the values at the constructor instead of the class declaration.
Because by default the variables are private. You must declare it as "protected", then will be properly inherited.
Related
I'm confused why this code works.
The object "person" is declared as an instance of B with only the functionality of A, yet it somehow prints out hello twice. If the object only gets access to the methods in A, how can it end up accessing the print out statement?
abstract class A {
abstract void move();
void go() {
this.move();
}
}
class B extends A {
void move() {
System.out.println("hello");
}
}
public class Main {
public static void main(String[] args){
A person = new B();
person.move();
person.go();
}
No, you have a "link" of class A, but functionality depends on object (in your code it is new B();), so your A link points to a B object with B functionality.
The object "person" is declared as an instance of B with only the functionality of A
Not exactly. Java is a reference-based language; here you have made an instance (new B()), and have exactly one reference to it, called person.
You could have no references to it (leading to the created object being garbage collected eventually). You can have 2000 references to it. You could have B b = new B(); A a = b;, and now you have 2 references to it, one of type A and one of type B. But they are pointing to the exact same object.
Thus, person isn't an object, it's a reference. And that reference has type A, sure, but the object it is referencing is just a B, it isn't 'restricted' to have only A functionality.
You probably know all this, but terminology is important here, as it seems to have led to some confusion. Restating your question with less ambiguous terminology:
The reference "person" currently references an instance of B, but only exposes functionality that A has.
Yes. And A's functionality is described solely by the signatures present there, not by the code. A's functionality involves having a go() method, which takes no arguments and returns nothing, as well as a move() method with the same rules. And that is all - 'invoking go will actually run the move method', or 'move has no implementation' is not part of that.
Thus, both move() and go() are part of the functionality exposed by A.
The implementation of the functionality has nothing whatsoever to do with the reference type (A person) and everything to do with what the reference is actually pointing at (new B()). B's implementation of the move() and go() methods specified by A are such that move prints "hello", and go() calls move (thus, prints hello()) - that implementation is inherited from A, but B was free to change that; B however decided not to.
Said more technically:
Java uses something called dynamic dispatch. What that means is that at compile time (i.e. write time), java figures out if a method you're calling even exists and which variant (if you have move(String a) and move(int a), that's two methods with the same name, at write time java decides which one you are attempting to invoke), and uses the type of the expression in front of the dot to figure that out. But then at runtime, the actual type of the object that 'the expression in front of the dot' is actually pointing at is used to figure out which actual code to invoke. This always happens and you can't opt out (you can't choose to run A's implementation when you invoke main(). Only B's implementation can choose to not override A's implementation, or to explicitly invoke its supertype's implementation. A user of B's code cannot do that).
Note that static stuff doesn't 'do' inheritance at all, and therefore, dynamic dispatch doesn't apply there.
A quick example
class A {
protected int foo(int x){
return x;
}
}
class B extends A {
public int foo(int x){
return x*x;
}
}
This is allowed in Java and works without any issue. But let's say in another package you declare
A b = new B();
int z = b.foo(5);
Then this won't work because obviously A foo() is protected. But then why allow in the first place to have more accessible methods in the subclasses? Is there a case where this is helpful?
In general, subclasses can add methods to the interface they inherit from their parent class. Making a method more accessible is effectively adding to the interface.
But then why allow in the first place to have more accessible methods in the subclasses?
Because it can be useful for code that holds a subclass reference.
Is there a case where this is helpful?
One good example is Object.clone(), a protected method. All Java classes are subclasses, directly or indirectly, of Object. Subclasses that support cloning can choose to make this method public.
Foo foo1 = new Foo();
Foo foo2 = foo1.clone(); // Sometimes you're holding a subclass reference.
Because classing is supposed to allow you to think of subclasses as instances of their superclasses. I think this is called an is-a relationship (namely B is-a A, but not the other way around). I don't really know a good way to explain this succinctly.
In your example, all instances of B are also instances of A (be mindful this may be a gross oversimplifaction, but I think for this example it is enough). A only guarantees to have methods that are public in its own definition. B just happens to make one of the protected methods public, but let's suppose you had another class called C that did not do this. Well, you can cast both B and C into A, but if you were allowed to call the protected method on A because B makes it public, then you would get an error when you pass C.
In the other package, you're casting B to A, so your object effectively takes on the interface of A so you are restricted to use only the interface given to you by A. Can the JVM go through the trouble and notice that 1) A is in fact B and that 2) B makes foo public, so foo should be callable? I mean it could I suppose, but how much effort would that take to implement in the JVM and how error prone would that be? Keep it simple. If the type is A, then the interface is A. If the type is B, then the interface is A and whatever else B includes on top of that.
You could make the second example compile if you replaced A with B. That's the point: B can be used everywhere A can, but can also add additional features (such as making methods public).
I have a parent class, A, and a child class, B, and B overrides a method, f, from A.
public class A
{
public String f()
{
return "A";
}
}
public class B extends A
{
...
public String f()
{
return "B";
}
public static void main(String[] args)
{
B b = new B();
A a = (A) b;
System.out.println(b.f()); //prints: B
}
}
I create an object of type B, b, and cast that to type A and assign it to a variable of type A, a, and then call the method f on a. Now I'd expect the method of the parent class to be called since I'm working with an object of Type A but it doesn't, it calls the b version of the method(prints "B" instead of "A" in the code below).
Why is it like this? Is it a design decision or a limit of technology?
This is basis of polymorphism
And it is supposed to work like that.
Any method is dispatched (selected/invoked) dynamically according to the actual type of the object in stead of the type by which it is being referred to.
When you cast the object to another type, you just refer it using another type. The actual type of the object is not changed. (And it can never change).
So the behavior that you are observing is as expected and it is designed to be that way. It's definitely not a limitation.
Hope this helps.
It's a design decision. You've created an object of type "B", so that's what it is.
When you cast it to A, you're only telling the interpreter that the methods expected to be found in a class of type A are available for B, but since you have an #Override method for B, it's going to use it.
A a = (A) b;
By casting the variable a the reference hasnt changed so the method f is still invoked since method calls are polymorphic
When you cast the instance you are simply implying that it could be an instance from the super class, BUT the internal implementation of that instance will not change, that's why you get that result!
Metaphorically speaking, if you applied an american's person mask on an UK person (cast), that person would still be english (inheritance), but if you asked that person to speak (calling a method) you would still hear the british accent, not the american one (internal implementation is what matters in the end) :-)
This is how it's supposed to work. It's calling the method on B because that's how the variable was instantiated as. The type of the variable it was assigned to does not change the fact that a is actually of type B. Most languages are like this, including C#.
I've studied that in case of instance methods, at run time the jvm uses the actual class of instance and in case of class methods the compiler will only look at the declared type of a reference variable not the actual class..
I studied this concept instance method hiding..
And in my proram I've used interface reference variable to store the object of the class and try to access the instance method of the class using this but it raise an error..
My program is as follows:
interface A
{
void show();
}
class B implements A
{
public void show()
{
System.out.println("Interface Method");
}
void info()
{
System.out.println("IN Info");
}
}
class interDemo
{
public static void main(String args[])
{
A a;
B b=new B();
a=b;
a.show();
a.info();
}
}
Please help me to understand the conept...
The compiler is telling you that the type A does not have a method called info defined. This is true: the compiler doesn't know that at runtime, the type of a will actually be B, which does have the info method. It would be unsafe to allow the a.info() call to actually be compiled and emitted into bytecodes, there's nothing to say that a will always be of type B.
This is known as static typing. In Java and other static-typed languages, you need to "cast" a variable in order to force the compiler to treat it as another type. In this case, you can write ((B) a).info().
sjr is correct. Here's another way to look at it:
You're specifying that a A can only show. That means when you have a A reference variable, that's all you can do.
That means any class that is willing to show can implement that interface. Clients that need an object to show can use an A without knowing or caring whether that the underlying class has other methods. This is a key aspect of the abstraction provided by object-oriented programming.
You might probably want to see this lecture on YouTube. It covers you problem and I hope it will help you.
In short: static type of a is A. After assigning b to a, dynamic type of a is B. So at this point, static type a is A and dynamic type of a is B. Compiler does not follow dynamic types, it only checks static types. So it will not let do anything other then static type will allow.
So in your example if you are using reference of static type A, you can only call methods from class A.
super concept without confusion
=====================================
2 rules to know from where a method will execute(when super type reference is used to call methods)
NOTE:check "object creation"/"reference assignment" statement for applying rule
1 RULE: 1st check the method to be called.If static/overloaded/single--then it becomes static polymorphism/static(compiler looks for reference type)---hence always execute from reference type
2 RULE: check method to be called --if overridden--then it becomes dynamic polymorphism(jvm looks for object type)---hence always executed from object type(i.e right to new keyword)
for example:
super s=new child();
s.play();
here 2 cases:
1st: check play() is what i.e static(static/overloaded/single method) or dynamic(overridden)
2nd: if static it will execute from super i.e reference type leads to compile time polymorphism
if dynamic it will execute from child i.e object type leads to dynamic polymorphism
I have something unclear concerning casting reference variable in Java.
I have two classes A and B. A is the super class of B.
If I have the two objects, and then the print statement:
A a = new A(); //superclass
B b = new B(); //subclass
System.out.println ((A)b);
then what exactly is happening when the println method is executed?
I know that because B is a subclass of A, I am allowed to make the following cast:
A a2 = (A)b;
I also know that when println takes a reference variable as argument, then the toString() method of the class, which has created the object-argument, is invoked (implicitly). This is so, because the method println() is looking for an argument of type String, and the toString() method represent the object as a string. And even if we don't write toString(), the method is invoked - implicitly. So, the following two statements are equivalent:
System.out.println (b);
System.out.println (b.toString());
So, my question is: what is the implicit action taken when we have
System.out.println ((A)b);
?
I suppose that the type of the reference variable b is automatically changed from B to A. The variable should still be pointing to the same object - the one created with
B b = new B();
but just the type of b would be now changed. Is this correct?
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
Thanks a lot.
Regards
The cast has no impact in this case.
The System.out.println(XXX) takes parameters of different types (multiple overloaded versions) but in this case you would get the version that takes Object. Since every object in Java supports toString(), toString is invoked on the actual argument, no matter what it is.
Now, since all methods in Java are dispatched dynamically, the version that runs is the version that corresponds to the dynamic type. Casting an object of B to A only changes the static (declared) type of the expression. The dynamic type (what's really in there) is still a B. Therefore, the version in B gets invoked.
There are many declarations of println(...) in the PrintStream class (which is the type of System.out).
Two of them are:
void println(String x)
void println(Object x)
When you call println((A)b) the compiler chooses to call println(Object) because A is not String (or any of the other types that println supports). When you call println(b.toString()), the compiler chooses println(String) because you are passing a String.
In your case, casting b to A has no effect since println() doesn't have a declaration for either A or B types. But the cast will still occur (because you asked for it), or maybe it won't because the compiler optimises it away as it knows it is redundant and it can't fail and has no effect.
It is not idiomatic to write:
A a2 = (A)b;
as this is redundant since B is a subclass of A. It may be that the compiler will optimise away the cast (which is a run-time operation to check whether an object is of a particular type, never to change it's type).
Once an object of type B is constructed, it's type never changes. It is always a B:
class B extends/implements A {...}
B b = new B(); // construct a B
A a = b; // assign a B to an A variable, it's superclass
A a = (A) b // as above including check to see that b is an A (redundant, may be optimised away).
B b = a; // Syntax error, won't compile
B b = (B) a // Will check whether a is of type B then assign to variable b
In the last case, since B is a subclass of A, it may be that a holds an instance of B and the cast will succeed. Or it may be that a holds an instance of some other class that extends/implements/is A and isn't a B and you'll get a ClassCastException.
So since an object of type B always retains it's identity (it's "B"-ness) then any (instance-) methods called on that object will always call B's implementation regardless of whether the variable through which you access the object was declared as A or B.
Remember, you can only call methods that are declared in the class that the variable is defined as.
So for example, if B declares a method b_only() then the compiler won't allow you to write a.b_only(); you could write ((B)a).b_only() though.
Since Java methods all have dynamic dispatch, which function gets called doesn't depend on the static type of the reference. Therefore, the results will be the same with or without the cast. [The results could be different if you were downcasting - the casting version could throw an exception]
Is this correct?
Sort of. The result of the casting expression would be of the A type. The type of the 'b' variable will always remain of type B.
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
The instance methods of the underlying object will be called. Example:
class Foo {
public static void main(String[] args) {
B b = new B();
assert "B".equals(((A) b).m());
}
}
class A {
String m() { return "A"; }
}
class B extends A {
String m() { return "B"; }
}
Always think of your object as the type it's instantiated as (B in your case). If it's upcast to A think of it as--hmm--think of it as B putting on A clothes. It may look like an A, and you may not be able to do any of the nice B things you want to do, but inside the clothes it's still a B--the clothes don't change the underlying object at all.
So the summary would be--you can only call the methods in A, but when you call it, it goes straight through and executes it as it would if it was a B.
I think when we use reference variable in java and by using this variable we can assign a object of any class type. most of the cases we create a reference variable of Interface and abstract class because we can't create the object of interface and abstract class so assign the object of class in reference variable of Interface or abstract class.
Ex-
Interface X {
public abstract void xx();
public abstract void yy();
}
Class XXX implements X {
...........
}
Class XY extends XXX {
X xy = new XXX();
}
here xy is a reference of Interface X and assign the object of Class XXX in the reference of Interface.
so according to my point of view by using reference variable we can also use interface to participate in Object creation.
The casting, as has been mentioned, is irrelevant in this case due to overridden methods being dynamically bound. Since the toString is present in all objects it meets this condition and thus the object type and method to call are determined at runtime.
Please note though, this is NOT the case with all methods since only overridden methods are dynamically bound. Overloaded methods are statically bound. Many of the answers here mention that java methods are always dynamically bound, which is incorrect.
See this question for a more detailed explanation.
question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
in this case the method of subclass b is called ; to convincingly understand why; you may relate to the following real world scenario
consider a parent class Father exhibiting a behaviour(method): height
defined as
the father is tall ;height = 6'2"
Son is a child class inheriting the height behavior from Father ;as a result he is also tall; height being 6' clearly overriding the behaviour
whenever your subclass Son calls the behavior height on his name he displays the overridden behavior i.e his own height 6' .