I was wondering why this piece of JAVA code produces a different output than the same code in C++.
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
public:
A(){
this->Foo();
}
virtual void Foo()
{
cout << "A::Foo()" << endl;
}
};
class B : public A
{
public:
B()
{
this->Foo();
}
virtual void Foo()
{
cout << "B::Foo()" << endl;
}
};
int main(int, char**)
{
B objB;
system("pause");
return 0;
}
This produces the output:
A::Foo()
B::Foo()
The JAVA code is:
public class Testa {
public Testa()
{
this.Foo();
}
public static void main(String[] args)
{
Testb b = new Testb();
}
void Foo()
{
System.out.println("A");
}
}
class Testb extends Testa {
public Testb()
{
this.Foo();
}
#Override
void Foo()
{
System.out.println("B");
}
}
This code produces only
B
B
Why is this output different in this case?
The difference is in the handling of polymorphism during construction. In Java, the dynamic type of the object is that of the derived class right away, allowing you to call member function even before the constructor gets a chance to set the member variables. This is bad.
C++ has a different approach: While the constructor runs, the type of the object considered to be the one of the class that the constructor belongs to. All calls to member functions are resolved statically according to that assumption. Consequently, the constructor of A calls A::foo(), while the constructor of B calls B::foo().
Edit
The first part of my answer was given before the Java Testa constructor was included.
In the Java code, you don't have a Testa constructor defined as in your C++ code. That explains why only one B is printed in Java.
But even if you did, to make the code more equivalent:
public Testa()
{
this.Foo();
}
It would print
B
B
Because in Java polymorphism works even when the method is called from the constructor. But that's not a good idea to do that, because the child part of the object Testb will still be uninitialized when the method Foo is called in Testb.
Related
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
Consider following Java program:
abstract class Surprising
{
void fun()
{
System.out.println("fun() is invoked");
}
}
class myclass
{
public static void main(String args[])
{
Surprising s=new Surprising() { };
s.fun();
}
}
Here I am creating object of nameless subclass of my abstract class Surprising, not the object of abstract class because it isn't allowed to create object of abstract class in Java.
What is the equivalent C++ program? Is it possible to do this in C++? If yes, how & if no, why not allowed?
Lets say we have the class A:
class A
{
...
};
Now to create a derivative of it, we use e.g.
class B : public A
{
...
};
Now to create an object of an anonymous class we simply don't provide a class name:
class
{
...
} anon_object;
And finally we combine the two ways, inheritance and anonymous classes:
class : public A
{
...
} anon_a_derived_object;
In C++ the Surprising class would not be abstract, because it defines all of its members. If you want an abstract (i.e. not instantiable) class, make at least one of its members pure virtual. Like here:
class Surprising
{
public:
virtual void fun()=0;
};
You can then define the member in an anonymous class of which you create an instance and then invoke the newly defined member function on that instance:
#include <iostream>
int main()
{
class : public Surprising
{
public:
virtual void fun() { std::cout << "Surprise!" << std::endl; }
} inst_;
inst_.fun();
return 0;
}
You cannot do this as on-the-fly as in Java, in the sense of declaring the class as part of the new expression. But you can create a local class inside the function and use it:
void main(int argc, char **argv)
{
class MySurprising : public Surprising {};
MySurprising s;
}
There are several differences between Java and C++ relevant to this question. I tried to produce the C++ code that most closely matches the Java code in question.
#include <iostream>
class Surprising // class is abstract since it has pure virtual method
{
public:
virtual void fun() = 0; // pure virtual method makes the class abstract
};
// we can define the pure virtual method, but not in class
inline void Surprising::fun()
{
std::cout<<"fun() is invoked\n";
}
int main()
{
struct : Surprising // anonymous derived class
{
void fun() // we must provide an implementation of fun()
{ // for otherwise this class remains abstract and
Surprising::fun(); // cannot be instantinated
}
} s; // object of anyonmous class
s.fun();
}
How does one force to invoke A's foo() method when working with instance of B (from main, and not through super call) ?
I could swear I've seen it done before. Perhaps it was C++ ??
public class Test {
static class A {
public void foo() {
System.out.println("A");
}
}
static class B extends A{
public void foo() {
System.out.println("B");
}
}
public static void main(String[] args) {
A a = new A();
B b = new B();
A aa = new B();
a.foo();
b.foo();
((A)aa).foo(); // want to print A here!
}
}
I could swear I've seen it done before. Perhaps it was C++?
The keyword here is virtual. This is possible in languages like C++ and C# because it's up to the programmer to define the method as virtual. I've adapted this code to C++:
#include <iostream>
using namespace std;
class A {
public:
void foo() {
std::cout << "A" << endl;
}
};
class B: public A {
public:
void foo() {
std::cout << "B" << endl;
}
};
int main() {
// your code goes here
A* a = new A();
B* b = new B();
A* aa = new B();
a->foo();
b->foo();
aa->foo();
return 0;
}
Prints:
A
B
A
Now, using the virtual keyword (just posting the relevant code from above example):
class A {
public:
virtual void foo() {
std::cout << "A" << endl;
}
};
Prints:
A
B
B
In Java you cannot expect this because all methods are virtual by default. So, to your question:
How does one force to invoke A#foo when working with instance of B and not through super call?
In Java, you can't.
You can't call the super method in other objects - that would violate encapsulation. The whole point is that the object controls what its overridden methods do. For instance, you might override a collection's add method to throw an exception in certain circumstances, so it could ensure only "valid" items got added to the collection. That would be pointless if callers could just bypass it with a cast!
The only reason an object gets to call super.foo() for itself is to enable one call to be implemented by using the parent implementation. It's up to the code in the class to make sure it only ever does that sensibly. Again, to take the add-in-a-collection example, if the collection overrides add it would have to have some way of adding the validated item to the collection, which it would do with super.add().
From outside the class definitions of A and B, you cannot force the superclass method to run. B has overridden it, so if an A reference refers to a B, B's foo method will run and print "B". No changes outside of these classes can change this polymorphic behavior -- having an actual B object will print "B".
To force it to print "B", you must change code in the A/B classes. You can mark foo as final in A so that B can't override it. Optionally, you can optionally include another method call in A's foo that B can override, so that A can guarantee that "A" will be printed, but B can still do whatever it wants when foo is called.
static class A {
public final void foo() {
System.out.println("A");
// Optional.
bar();
}
protected void bar() {}
}
static class B extends A {
// Can't override "foo" now -- can't prevent "A" from being printed.
//public void foo() {
// System.out.println("B");
//}
// Optional.
#Override
protected void bar() {
System.out.println("B");
}
}
Here, foo will always print "A", but B can also print "B" if it really wants.
Ok! I have same code written in Java and C# but the output is different!
class A
{
public void print()
{
Console.WriteLine("Class A");
}
}
class B : A
{
public void print()
{
Console.WriteLine("Class B");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.print();
Console.Read();
}
}
Output: Class A. It is in C#.
But when same code was ran in Java, the output was Class B. Here is the Java Code:
class A
{
public void print()
{
System.out.println("Class A");
}
}
class B extends A
{
public void print()
{
System.out.println("Class B");
}
}
public class Program{
public static void main(String []args){
A a = new B();
a.print();
}
}
So, why this is showing different results? I do know that, in Java, all methods are virtual by default that's why Java outputs Class B.
Another thing is that, both languages claim that they are emerged or inspired by C++ then why they are showing different results while both have same base language(Say).
And what does this line A a = new B(); actually doing? Isn't a holding object of class B? If it is so, then why C# displays Class A and Java shows Class B?
NOTE This question was asked in interview with the same code provided above. And I answered with output Class B (with respect to Java) but he said Class A will be right output.
Thank you!
This is because in C# methods of derived classes hide, not override, methods of their base class. The methods that you would like to override need to be explicitly marked with the keyword virtual in the base, and with the keyword override in the derived classes.
In contrast, in Java all methods are virtual by default: simply specifying the same signature is sufficient for an override.
Here is how to make your C# program an equivalent of Java program:
class A
{
public virtual void print() // Add "virtual"
{
Console.WriteLine("Class A");
}
}
class B : A
{
public override void print()// Add "override"
{
Console.WriteLine("Class B");
}
}
After A a = new B(), variable a is holding object of B but the output is "Class A"! Shouldn't it call method of class B?
When you hide a method, rather than overriding it, your derived class keeps both methods - the one in the base class, and the one in the derived class. Both these methods remain accessible to the outside callers. They can decide which of the two methods to call by using an object of an appropriate static type. Here is an example:
B b = new B();
b.print(); // Prints "Class B"
((A)b).print(); // Prints "Class A"
Demo on ideone.
When you use virtual/override, you can access only one method from the outside - namely, the one in the derived class. The method in the base class can be accessed by methods of the derived class, but not by the outside users of the derived class.
In Java, non-static methods are virtual, whereas in C#, they are not. You will need to use the virtual and override keywords on your print method to get the same behaviour in c#.
Polymorphic behaviour in C#:
class A
{
public virtual void print()
{
Console.WriteLine("Class A");
}
}
class B : A
{
public override void print()
{
Console.WriteLine("Class B");
}
}
Edit
Getting back to your original C# code, you will get a compile time warning on B.print when you use the same method signature in both a subclass and its superclass, viz:
The keyword 'new' is required on 'print' because it hides method
'MyNamespace.A.print()'
This is a good indication that the method won't be called polymorphically / virtually. To avoid the warning (and retain your original C# behaviour), in B you would need to add new:
public new void print()
I've heard that all Java functions are implicitly virtual, but I'm still not sure if this will run how I want.
Suppose I have a class A, with child B.
both A and B have functions called foo(), so B's definition is overriding A's.
Suppose also that A has a function called that takes an instance of A as a parameter:
If I pass in an instance of B to the function, which definition of foo() will it call, A's or B's?
As I mentioned in my comment private functions are not virtual and I want to demonstrate it using following example:
class A {
public void foo() {
System.out.println("A#foo()");
}
public void bar() {
System.out.println("A#bar()");
qux();
}
private void qux() {
System.out.println("A#qux()");
}
}
class B extends A {
public void foo() {
System.out.println("B#foo()");
}
private void qux() {
System.out.println("B#qux()");
}
}
Now lets run following code:
A foobar = new B();
foobar.foo(); // outputs B#foo() because foobar is instance of B
foobar.bar(); // outputs A#bar() and A#qux() because B does not have method bar
// and qux is not virtual
B's implementation will be called.
That's exactly what virtual means.