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.
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
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.
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.
Is it possible in Java to invoke an overridable method in such a way that it always executes the "locally defined" version rather than an overridden version from a subclass? I.e. is there an analog to super that refers to this class, rather than the super class?
Let me give a code example to hopefully make it clear what I'm trying to do:
class A {
void foo() {
System.out.println("Foo from A");
}
void bar() {
foo(); // <-- This is the important line!
}
}
class B extends A {
#Override
void foo() {
System.out.println("Foo from B");
}
}
If I do new B().bar(), it will call the bar() method defined in A, which calls foo() as overridden in B to print "Foo from B".
Is there a way that I can force the bar() method to call the foo() method as defined in A rather than B? Just like I can use super.foo() in B to call the foo() method as defined in A? Unfortunately using this.foo() still calls the version of the subclass. Even something like ((A) this).foo() or A.this.foo() doesn't work.
Clearly, I could simply define a private or final version of foo() in A and call that instead. But I am hoping for a solution, where all I do is change the "important line" in the code sample above to a different way of invoking foo() to have it print "Foo from A", preferably without some trick like reflection.
Your object is a B. It isn't an A! Here's an example:
public class Apple {
public void printColor() {
System.out.println("I am red");
}
public void bar() {
printColor();
}
}
Then the subclass:
public class GrannySmithApple extends Apple {
public void printColor() {
System.out.println("I am green");
}
}
GrannySmithApples are green, always (unless they are rotten, but that's a whole other can of bananas)! Once you have a GrannySmithApple, it's not an Apple anymore, except in the sense that you can do all the same things with it that you could a regular Apple (printColor, eat, etc.) Make sense? And anything that hasn't changed between the conversion from regular Apple to GrannySmithApple is obviously still the same.
You can have an "internal" foo() in A that is called.
class A {
private void fooInternal() {
System.out.println("Foo from A");
}
void foo() {
fooInternal();
}
void bar() {
fooInternal();
}
}
class B extends A {
#Override
void foo() {
System.out.println("Foo from B");
}
}
new B().bar() will now print "Foo from A" while new B().foo() will print "Foo from B".
Either make your methods static (baadddddd), either change your design.
Indeed, it makes no sense to provide the default behavior for a subclass that it is defined to adapt itself to the concerned method.
As your foo() method seems to vary, you may implement a Strategy Pattern like this:
interface BarProcess{
void foo();
}
public class DefaultBarProcess implements BarProcess{
void foo() {
System.out.println("Foo from A");
}
}
public class AnotherBarProcess implements BarProcess{
void foo() {
System.out.println("Foo from B");
}
}
class A {
private BarProcess barProcess;
public A(Bar barProcess){
this.barProcess = barProcess;
}
void bar() {
barProcess.foo();
}
}
class B extends A { //deprecated! No need to exist
}
As far as I know, a B object will always call its own foo() method. With that said, B.foo() can be defined to call the superclass' foo() method. For example, you could define B as follows:
class B extends A {
#Override public void foo() {
super.foo();
}
}
And doing so will have B call foo from A. But doing so will have it always do so.
There is this Rule of Thumb:
In Inheritance the most specific version of the method for that class is called.
- So it will be always the foo() method of Class B that will be called, if its called on an instance of B.
- Still if you want the foo() method of Class A to be called using your above mentioned code then you will need the super keyword.
Eg:
class B extends A {
#Override
void foo() {
super.foo();
}
}
foo() always invokes instance method of the class used in new ... statement.
In short I think that the answer to your question is NO, it can't be done. It would prevent you from overriding parts of behaviour completely.
class A {
method1() {
...
method2();
...
}
class B extends A {
// You can override method2 here to change the behaviour of method1
// because it will call **your** version of method2
// You **don't** have to override method1 to achieve that
method2() {
...
}
}
this references "this object", not "this class".
That means if you have an object B that extends A, when it executes a method in the superclass A that mentions this, it will actually point to the instance of B, so will execute the method on B.
You can think of the method in A as a default method. If the method is overridden in your actual object B, then it will always be called instead.
I suggest you change your design and use composition instead of inheritance: that would ensure a clear separation of concern, and make your code a lot easier to understand and test.
As others have stated there is no direct way to do it but you might consider a variant of this construct:
void bar() {
ClassA self = new ClassA();
self.foo(); // <-- This is the important line!
}
Let's say I have two classes, A and B, in turn have some methods, something() and nothing() and an instance of B is created in A, as
public class A {
public A() {
B b = new B();
b.nothing();
}
public void something() {
...
}
}
A calling b.nothing() is all standard stuff, but is there any means which by instance b can call a.something(), assuming the instance of A is called a. If not, why is this conceptually wrong?
I don't think there's anything conceptually wrong with this.
However, for the mechanics to work, b needs to know which instance of A to call something() on. For this, either B's constructor, or its nothing() method, needs to take an A reference as an argument.
example 1:
public class B {
public void nothing(A a) {
...
a.something();
...
}
}
example 2:
public class B {
private final A a;
public B(A a) {
this.a = a;
}
public void nothing() {
...
this.a.something();
...
}
}
example 3:
There is a third way, applicable in some circumstances. If B is an inner class of A, it has an implicit reference to its associated instance of A.
public class A {
public void something() { ... }
public class B {
public void nothing() {
...
something();
...
}
}
}
is there any means which by instance b can call a.something()
You can't get hold of the caller in a method so, no, there's no way to do that.
If not, why is this conceptually wrong?
Two issues come to my mind immediately:
What would the type of the caller be? Since anyone could call b.nothing(), you can't assume more than that it's an Object which would result in lots of ugly down casts.
The implementation of b.nothing() shouldn't care about who's calling him. What happens if you refactor A and move the call to b.nothing() to some other class? It would be quite surprising if b.nothing() all of a sudden stopped working.
The only way b.nothing() can call a.something() is if you tell the instance of B about the instance of A. For example:
b.nothing(this);
where B.nothing looks like:
public void nothing(A a)
{
// Do other stuff
a.something();
}
Alternatively, you could pass in this in the constructor to B, which would keep hold of the reference:
B b = new B(this);
b.nothing();
Note that letting this escape during a constructor call is generally a bad idea - you're letting B.nothing() call A.something() on an object which isn't fully initialized yet - its constructor hasn't finished executing. That can lead to undesirable and hard-to-diagnose behaviour sometimes.
To do this, b would require a reference to a. There are two ways to provide that:
Pass such a reference in the constructor of B or give B an appropriate setter.
If B is an inner class of A, then it has such a reference implicitly.