This question already has answers here:
Method overloading using derived types as parameters in Java
(3 answers)
Closed 4 years ago.
I want to know why the third output is NOT b.
Here is my code:
public class SimpleTests {
public void func(A a) {
System.out.println("Hi A");
}
public void func(B b) {
System.out.println("Hi B");
}
public static void main(String[] args) {
A a = new A();
B b = new B();
A c = new B();
SimpleTests i = new SimpleTests();
i.func(a);
i.func(b);
i.func(c);
}
}
class A {}
class B extends A {}
And here is the output:
Hi A
Hi B
Hi A
Could someone tell me why the 3rd output is Hi A, NOT Hi B. as the real c is a instance of B.
You're confusing overloading with polymorphism.
With polymorphism, when creating an instance of class B which is a subclass of class A, referenced to by an class A object, and overwrites the method of class A, calling the method will perform the method of class B.
With overloading, the called method only knows the type of the declaration of the argument, not the initialization.
public class A {
public void print() {
System.out.println("A");
}
}
public class B extends A {
#Override
public void print() {
System.out.println("B");
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
A otherB = new B();
a.print();
b.print();
otherB.print();
}
}
This will output
A
B
B
Calls to overloaded methods are resolved based on the reference type (A) of the argument at compile time, not the object type (B) at runtime. You declared the variable to be of type A, so it is treated as type A.
JLS ยง8.4.9. Overloading:
When a method is invoked, the number of actual arguments (and any
explicit type arguments) and the compile-time types of the arguments
are used, at compile time, to determine the signature of the method
that will be invoked.
The compile-time types in your example are:
A a = new A(); // A
^
B b = new B(); // B
^
A c = new B(); // A
^
Therefore, the output is:
Hi A
Hi B
Hi A
Related
This question already has answers here:
What is method hiding in Java? Even the JavaDoc explanation is confusing
(8 answers)
Closed 5 months ago.
My questions are:
Why method hiding is also an example of compile time polymorphism while it is not overridden?
Related code:
class A{
public static void print(){
System.out.println("class A");
}
}
public class B extends A{
public static void print(){
System.out.println("class B");
}
public static void main(String[] args){
A a = new B();
a.print(); //class A
B b = new B();
b.print(); //class B
}
}
If Method hiding is also an example of compile time polymorphism then why variable hiding not an example of compile time polymorphism while variable hiding like method hiding are not overridden and polymorphic?
Sorry my english is pretty bad.
https://byjus.com/gate/difference-between-compile-time-and-run-time-polymorphism-in-java
Q: What Is Compile-time Polymorphism?
A: Compile-time polymorphism is obtained through method overloading.
The term method overloading allows us to have more than one method
with the same name. Since this process is executed during compile
time, that's why it is known as Compile-Time Polymorphism.
Your code won't compile as-is. Here's an alternate version:
B.java:
class A{
public static void print(){
System.out.println("class A");
}
}
public class B extends A{
public static void print(){
System.out.println("class B");
}
public static void main(String[] args){
A a = new A();
a.print();
B b = new B();
b.print();
A c = new B();
c.print();
//System.out.println(a.a);
}
}
Output:
class A
class B
class A
You'll notice:
A.print() => "class A" // Expected
B.print() => "class B" // Also expected
class B "is a" A // We can instantiate "B", but use it as "A"
C.print() => "class A" // When we do so ... it BEHAVES as "A"
This example illustrates compile time behavior
Now let's try a different example, without "static":
class A2{
public void print(){
System.out.println("class A2");
}
}
public class B2 extends A2{
public void print(){
System.out.println("class B2");
}
public static void main(String[] args){
A2 a = new A2();
a.print();
B2 b = new B2();
b.print();
A2 c = new B2();
c.print();
//System.out.println(a.a);
}
}
Output:
class A2
class B2
class B2
This is an example of runtime polymorphism.
I'm studying for a Java-exam and have a question concerning static and dynamic types.
I've got 4 classes: A, B, C and Main.
public class A {
private void tell(){
System.out.println("AA");
}
}
public class B extends A {
public void tell(){
System.out.println("BB");
}
}
public class C extends B {
}
public class Main{
public static void main(String[] args) {
A c = new C();
c.tell();
}
}
My suggestion was: the output should be "BB", because c has the dynamic type C. Since C doesn't have the method "tell" the method of the upper class B is used, which prints "BB".
The outcome however is an error, because Java looks for "tell" in A. In A it of course can't find it, because there it is declared priavte. But why does it look in A, although only it's static type is A, but it's dynamic type is C?
You are getting an error because at compile time, the compiler does not know the actual instance that will be put in A, so when the compiler sees c.tell() he only looks at the class A which indeed does not have an acessible tell() method.
One way to understand this is with this example:
public class A {
private void tell(){
System.out.println("AA");
}
}
public class B extends A {
public void tell(){
System.out.println("BB");
}
}
public class C extends A {
}
public class Main{
public static void main(String[] args) {
A b = new B();
b.tell();
A c = new C();
c.tell();
}
}
You can see that the first 2 lines would be ok (by your current logic of thinking). B has the method tell() so b should be able to call tell(). But using the exact same assignment with another subclass of C which does not have the tell() method then your logic would fail. A nor C have the tell() method so the program suddenly has a call to a method that does not exist or is not accessible.
Say I have the following code
public class A {
public void callme() {
System.out.println("Calling of class A function ");
}
}
public class B extends A {
public void callme() {
System.out.println(" Calling of class B fuction ");
}
public void Hello() {
System.out.println("hello guys");
}
}
and a main() that does the following
public class Main {
public static void main(String [] args){
A a = new B();
B b = new B();
b = (B)a;
a.callme();
b.callme();
a.Hello(); // show error : Hello is undefined for method A
}
}
The book says "you get the behavior associated with the object to which the variable refers at runtime". Ok, I get behavior of B class when a method callme is called, but when I access the method Hello, it shows an error that Hello is undefined for method A. why is that?
Polymorphism doesn't work this way. Since A is parent of B, B can inherit methods of A (like son can inherit properties of father), but its not vice versa because A doesn't know which classes are inheriting it (A does not know who are its children.)
For Example, suppose there is one more class C:
public class C extends A {
public void callme(){
System.out.println(" Calling of class C fuction ");
}
public void Hello(){
System.out.println("hello guys, I am C");
}
}
Now, if you use
a.Hello();
how will a know which child class it should call since it does not methods of its child. only its own abstract method, which it knows child will implement for sure.
a is of type A, even if it is referring to an instance of B.
A doesn't have the Hello method (even an abstract declaration). So your compiler emits the error. Adjusting your code slightly to
public abstract class A {
public abstract void Hello();
/*the rest as before*/
would be a fix. A is then assuming the characteristics of an interface.
public class B extends A {
public void callme(){
System.out.println(" Calling of class B fuction ");
}
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In above class hello() method is a part of B only. it not override by the method of A.
now in your main method call
public static void main(String [] args){
A a= new B(); // object of b referred by (a) Reference Variable of A
B b= new B(); // object of b referred by (b) Reference Variable of B
b= (B)a;
a.callme(); //override takes place and method of B's Callme() called
b.callme(); //again override takes place here and method of B's Callme() called
a.Hello();// buttttttt
b.Hello(); // this will compile and executes fine.
}
}
Here you used the reference variable of class A which don't have any method name Hello(). So, Method Resolution will not take place(won't be able to find any method like Hello()).
but if you try to call b.Hello() using the reference variable of B then it will work fine to you.
Now suppose there is another class C which is a sub class of A and contains a Method Name Hello().
public class C extends A {
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In main a Statement like this
A a = new C();
and if you try to call a.Hello() then which Hello() method will call. Compiler will get confused.
So, This concept work only when you try to override the method of super class in sub Class.
Is the parent class aware of classes derived from it ?
Casting does not change the actual object type. Only the reference type gets changed.
I highly recommend you my upcasting and downcasting writing from the link
I have these two classes:
public class A {}
public class B extends A {}
In the main class, I would declare:
A a = new B();
B b = new B();
What is the difference between a and b ? Is this what we called a subtyping in java?
The difference between a and b is that with a you can only use the public API that the A class provides even though its really a B type object, but with b, you can use both the A's public API as well as B's public API.
For example:
Suppose A and B are defined as follows:
// A.java
public class A
{
public void x()
{
z("X");
}
public void y()
{
z("Y");
}
protected void z(String message)
{
System.out.println(message);
}
}
// B.java
public class B extends A
{
public void a()
{
z("A");
}
public void b()
{
z("B");
}
}
And here's a demo:
// Demo.java
public class Demo
{
public static void main(String[] args)
{
A a = new B();
B b = new B();
// Can only call A's public methods
a.x();
a.y();
// a.a(); Can't use
// a.b(); Can't use
// Can call all public methods
b.a();
b.b();
b.x();
b.y();
}
}
Yes, there is difference between them. Accssibility of methods are different depends on what kind of reference you use.
A a = new B();
B b = new B();
a is a reference of Class A and b is a reference of class B. super class always can be used to point subclass object.
reference a able to access only super class method and properties
reference b able to access super class and it's own method and properties
one important thing is, ability of accessibility of function and properties will decided at runtime.
In below two cases
A a = new B();
a is an instantiation of B and of type A.
whereas in
B a = new B();
a is an instantiation of B and of type B.
The important thing to note here is that (in the first case) if you call a.someMethod(), the method of B will be called, not the method of A (this is called dynamic binding, as opposed to static binding).
This is basic inheritance. In the B b = ... case you can access all methods and variables provided from A and B but in the A case you can only use the methods and variables in the A case.
B gets typecasted into A when it is created, but that information is not required by the compiler.
public class A {
int x;
}
public class B extends A {
int y;
}
A a = new B();
B b = new B();
int c = a.x; //works
int c = a.y; //doesn't work
int c = b.y; //works
int c = b.x; //works
Remember, that you can always cast an object "downwards" in the inheritance chain. But you should not cast a object upwards because the variables for the subclass might be used even though they dont exist, for exmaple B b = new A(); So b.y is dangerous since the B object doesn't have an y variable defined.
I need help with this Java Program example. This example is from the book
Java: Seventh Edition by Herbert Schildt.
I have few doubts about this program and also doubts about the text(explanation of this topic) written in this book. This program is written under Inheritance --> Method Overriding. Here A is the super class of B and B is the super class of C. In this program callme() is a method written in the three classes where each callme() overides another callme() method.
1) In the program below, what does obtain a reference of type A means? (This concept is implemented in the line A r; in the Main method)
2) What is name space convention?
3) In this program, what does "r referes to an A object mean"? (This concept is implemented in the lines r.callme(); written in the main method.)
class A
{
void callme()
{
System.out.println("Im in the class A");
}
}
class B extends A
{
void callme()
{
System.out.println("Im in the class B");
}
}
class C extends B
{
void callme()
{
System.out.println("Im in the class C");
}
}
public class Dispatch
{
public static void main(String args[])
{
A a = new A();
B b = new B();
C c = new C();
A r;
r = a;
r.callme();
r = b;
r.callme();
r = c;
r.callme();
}
}
This is a way to overcome the problem of method over-riding.
If you want to get rid of method over-ridden at some time during your development then you can use this way of DMD.
Referring your example with comments:
class A //Super class A
{
void callme() // method callme() that'll be overwritten next in subclasses
{
System.out.println("Im in the class A");
}
}
class B extends A //Subclass B inherited from A
{
void callme() //method callme() of Super class A is over-hided here
{
System.out.println("Im in the class B");
}
}
class C extends B //Subclass C, inherited from B
{
void callme() // this time B subclass method callme() is over-hided
{
System.out.println("Im in the class C");
}
}
//Now suppose, during you development phase at some time, you don't want to use over-ridden methods, here is DMD to help you out at run time.
public class Dispatch
{
public static void main(String args[])
{
A a = new A();
B b = new B();
C c = new C();
A r;
// r is a reference to class A
// this reference should be assigned to each type of object and called at
// run time without compiling.
r = a;
r.callme();
r = b; r.callme();
r = c; r.callme();
}
}