This is what I'm trying to do:
class A {
void myMethod() {
// execute A
}
}
class B extends A {
void myMethod() {
// execute B
}
}
class C extends B {
void myMethod() {
// execute C
// execute myMethod in A, without touching myMethod in B OR both
}
}
I'd like to do this conditionally, that is sometimes call what's in myMethod inside B and other times not, but always call myMethod inside A.
By calling super.myMethod() in C I get myMethod of B, but I only want myMethod of A. Is that possible? I've heard of "virtual" things, but I don't know how to use them... yet.
No, it is not possible in Java on purpose. Class B overrides and therefore hides the implementation of myMethod in A from further deriving classes. Allowing C to call myMethod of A would violate this encapsulation. Consider a case where B.myMethod performs some updates before internally calling A.myMethod which are important for the correct functionality of B. Without these updates, the contract of B could be violated. Therefore, it should not be possible to call A.myMethod in a derived class without calling B.myMethod.
Usually, your design is flawed if you want to do stuff like this.
Of course, you can do stuff like suggested by Dave in the comments: You can alter the implementation of B.myMethod to call A.myMethod. This is okay, because B retains the control over when to call A.myMethod. Therefore, it can take care that its contract is not violated.
Another idea is to factor out the behaviour you want from A into another method and call this one.
If you need this, A.myMethod() probably does too much. Try to refactor it into several smaller methods with access level protected.
That allows you to call these methods from both B and C.
While I agree with most answers about possibly changing the design, to directly answer you could pass in a variable boolean into the first method. The entirety of the logic in B's method should depend on a conditional if statement depending on the boolean. Make sure to make a call to super.myMethod() outside of this if statement.
Something like this:
void myMethod(boolean execB) {
// execute B
super.myMethod(execB);
if(execB)
{
//B logic
}
}
This is however, not the best in practice, because only B's method is using the variable, hence why refactoring the design might be a good decision.
Related
I have a class A:
A
- void method1
And a class B that extends A that overrides A's method1:
B->A
- void method1
Later on, I create an instance of B that is referenced as an A:
A a = new B();
I want to use A's version of method1 in a specific case. Is there a way to call this, like:
a.super.method1();
Edit:
To clear up any confusion, here is what I am trying to accomplish:
I have a parent class called Account. Beneath that I have 3 subclasses, SavingsAccount, CheckingAccount, and MoneyMarketAccount.
Each of these has its own deposit/withdraw methods that have specific fees associated to them.
There is a manager class called Bank that has an ArrayList of Account objects in it. I have a method, void transfer that I am attempting to create that will allow me to take the two accounts and transfer the money between them.
Sometimes the different methods will throw exceptions if there are insufficient funds or other errors, so I need to be able to reverse a transaction if it fails for one of the two accounts.
This is where I am having problems:
I need to redeposit the money withdrawn from the from-account if the to-account can't receive deposits, but the to-account may have deposit fees, so I would like to just call the parent Account class's deposit method, as it does not have any fees associated; however, from the comments and answers that I have received, I may have to just write another method that is not overridden that simply performs the same operation as Account's deposit.
You can't use super directly since it only exists inside of B. But you can do it indirectly:
public B extends A {
public void method1() {
// B's method 1
}
public void superMethod1() {
super.method1();
}
}
So if a class uses a B variable, then they can call the superMethod1() and get A's method1.
But having said this, this won't work on A variables, as your code is currently set up, not without casting.
i.e., you could do:
B b = new B();
b.superMethod1();
But this won't work for your set up:
A a = new B();
// not without casting
((B)a).superMethod(); // ugh... ugly! AND dangerous!
Note that your question, while itself not bad, suggests possibly a bad program design and code needing this has at least for me, a bad code smell.
You can have super or this keywords only with in the class. You cannot use them outside of that class.
So with in the class you can do (Mock code)
class A {
someMethod(){
super. someMethod()
}
}
You can't do that from the client code, ie. the code calling the method. You can only do it within the sub class method
super.method1();
and only for one level up the hierarchy.
use A a = new A(); or you can call super.method1() from B's method1 if you want to go like A a = new B();
I think it's not very useful question, but i think someone can say smth critical.
public class Base{
public void boo(){}
}
public class Derivative extends Base{
1:public void useBoo(){
boo();
}
2:public void useBoo(){
this.boo();
}
3:public void useBoo(){
super.boo();
}
}
[EDIT]
The reason why I asked this question : to avoid recompilation or name confusion in future. And make code more readability and flexable to future changes.
The best one to use is the one you feel is clearest.
BTW: The first example will behave different to the third example, if you add a boo method to Derived.
If you want to be sure that the method invoked is the super class method, definitely use super:
super.boo();
If you want to use a method defined in the current class and if this is not present use the super method use:
this.boo();
//or
boo();
Personally in the second case, if the class is part of a hierarchy, I prefer to explicitly use this.boo() because it's more clear reading the code, to understand where the method is supposed to be. But it's my opinion.
I would only use 1 and 2 (in my case I prefer 2, I like to be explicit about my intentions)
public void useBoo(){
this.boo();
}
I wouldn't use 3 because it means something else semantically, remember that Derivative can also be extended, and boo() may be overridden further down the class hierarchy, and unless you specifically want to call Base.boo() you shouldn't use the super keyword.
Use one of the first two, unless you explicitly want to limit the call to the superclass implementation.
When you override a superclass method, and want to include the behavior of the superclass method, use the third.
Elsewhere, if you use the third, and later you or someone else overrides the superclass implementation of boo() -- in this class or a subclass -- then useBoo() will not use the override. This is usually undesirable except in the override of boo() itself.
Examples:
/** Extends boo method. */
public void boo(){
super.boo(); // Good: you explicitly want to call the superclass method, not call this method again.
}
public void doSomethingThatInvolvesBoo() {
boo(); // Good -- will call this object's implementation,
// even if this is a subclass, even if there are code changes later.
this.boo(); // Good (and equivalent to simply calling boo()).
super.boo(): // Usually bad.
}
Is there anything stopping you from just calling boo()? Or have you overridden it in your own code?
1 and 2 do the same thing, 3 calls the method of Base.
edit: as Simeon said, using super would make it very clear you are calling the method from the Base class.
Having readability in mind super is probably the best because it says here I'm invoking a method from the super class.
While with this you could wonder 'where the hell is this method .. oh ok its in the super class'
Suppose I have class A
public class A
{
public void method()
{
//do stuff
}
}
Also another class B
public class B extends A
{
public void method()
{
//do other stuff
}
}
Now I have the following statements:
A a = new B();
a.method();
Is this an example of run time polymorphism? If yes, then is no binding is done for the reference a at compile time?
The compiler will tell you that this can't work, because there's no relationship between A and B that will allow you to write A a = new B();
B either has to extend A or both have to implement a common interface with void method() in it.
You could have answered this very quickly by trying it with the compiler. Be an experimentalist - it's faster than forums.
UPDATE:
It works, now that B extends A. The binding that you care about, dynamic binding, is done at runtime. The static compile time type for the variable "a" is class A; at runtime it is dynamically bound to a reference of type B. Yes, I would consider this to be an example of polymorphism.
I was waiting to put my answer to another post, into a more correctly classified problem. Your question fits the concept, I've tried to explain in detail. but, since I don't know how link answers, I'll just copy/paste the complete script here .... Kindly go through it, you'll understand everything that there is to understand about your problem, you've asked
let's say compiler has to resolve a call like this : *
A a = new AA(); // Assume AA to be some subclass of class A
a->someFunc(); // and we're invoking a method "someFunc()' on a
*.
Now, compiler will go over following steps methodically.
1.) Firstly, compiler knows the declared type of variable a, so it will check whether the declared type of object a (lets call this, class A for time being), have a method with the name someFunc() and that it must be public. This method could either be declared in class A, or it could be a derived method from one of the base class(es) of class A, but it doesn't matter to compiler and it just checks for it's existence with it's access specifier being public.
Needless to say any error in this step will invite a compiler error.
2.) Secondly, once the method is validated to be a part of the class A, compiler has to resolve the call to the correct method, since many methods could be there with same name (thanks to function overloading). This process of resolving correct method is called overloading resolution. Compiler achieves this by matching the signatures of the called method with all the overloaded methods that are part of the class. So, of all the someFunc() s only the correct someFunc() (matching the signatures with called method) will be found and considered further.
3.) Now comes the difficult part, It may very well happen that someFunc() may have been overridden in one of the subclasses of the class A (lets call this class AA and needless to say it is some subclass of A), and that variable a (declared to be of type A) may actually be referring to an object of class AA, (this is permissible in C++ to enable polymorphism). Now, if the someFunc() method is declared to be of type virtual, in base class (i.e. Class A) and someFunc() has been overriden by subclass(es) of A (either in AA or classes between A and AA), the correct version of someFunc() have to be found out by the compiler.
Now, imagine you're the compiler and you have this task of finding whether the class AA has this method. Obviously, class AA will have this method since, it is a subclass of A and public access of A in class A has already been validated in Step 1 by the compiler !!! . But Alternatively, as mentioned in previous paragraph, someFunc() may be overriden by class AA (or any other class between A and AA), which is what compiler needs to catch. Therefore, you (since, your'e playing the compiler) could do a systematic check to find the bottom-most (lowest in the inheritance tree) overridden method someFunc() starting from class A and ending at class AA. In this search, you'll look for same method signatures as was validated in overloading resolution. This method will be the method which will be invoked.
Now, you may be wondering, "What the heck", is this search done everytime ? ... Well, Not really. The compiler knows the overhead of finding this everytime, and as such, maintains a data-structure called Virtual Table for every class type. Think of virtual table, as mapping from method signatures (which are publicly accessible) to the function pointers. This virtual table is made by compiler during compilation process and is maintained in-memory during program execution. In our example, class A and class AA will both have their own virtual tables. And when compiler has to be find someFunc() in class AA (since actual object pointed by variable a is of type AA), it will simply find the function pointer through the virtual table of Class AA. This is as simple has hashing into the table and is a constant time operation.
Regards
AViD
The code example you've given isn't legal, so I guess the answer is that it's not a kind of polymorphism.
You can't assign a class to a variable of an unrelated type like that. I'm guessing that you might be intending for B to derive from A?
Is this an example of run time polymorphism?
As of the edit: yes that would be runtime polymorphism, since which method is actually executed depends on what is assigned to a.
Edit:
If method() would be static, then calling a.method() would always result in the version of A being called. However, you'd then just write A.method() and if you don't do that any decent IDE would warn you about that (because it might be misleading to call a static method on an instance).
End Edit.
Compile time polymorphism would be the overloading mechanism, i.e. the compiler decides whether to use someMethod(Number) or someMethod(Integer) depending on what it knows about the parameter that is passed (if you pass a Double or just a Number it would be the first one, if you pass an Integer it would be the second).
If yes, then is no binding is done for the reference a at compile time?
What do you mean exactly? Note that the type of a will be A so you can assign everything that extends A at runtime. The compiler will just complain if the assigned value is not an A (you might trick the compiler with a cast, but this is just evil and if this breaks your program, you have been warned ;) )
It should be
public class B extends A {
public void method()
{
//do other stuff
} }
If it were compiling, it would be the B::method() that would be called. (only if you changed your code to make the B class inherit the A class).
In this case your use your object like it was only an A, but if some methods are overidden in B, then these methods are called, instead of A's methods.
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.
Referring here
A is a precompiled Java class (I also have the source file)
B is a Java class that I am authoring
B extends A.
How can logic be implemented such that A can call the methods that B has.
The following are the conditions:
I don't want to touch A(only as a
last option though that is if no
other solution exists).
I don't want to use reflection.
As stated, if needed I could modify A.
What could be the possible solution either way?
Class A should define the methods it's going to call (probably as abstract ones, and A should be an abstract class, per Paul Haahr's excellent guide); B can (in fact to be concrete MUST, if the method are abstract) override those methods. Now, calls to those methods from other methods in A, when happening in an instance of class B, go to B's overrides.
The overall design pattern is known as Template Method; the methods to be overridden are often called "hook methods", and the method performing the calls, the "organizing method".
Yes it seems that if you override the super/base-classes's functions, calls to those functions in the base class will go to the child/derived class. Seems like a bad design in my opinion, but there you go.
class Base
{
public void foo()
{
doStuff();
}
public void doStuff()
{
print("base");
}
}
class Derived extends Base
{
#Override
public void doStuff()
{
print("derived");
}
}
new Derived().foo(); // Prints "derived".
Obviously all of Derived's methods have to be already defined in Base, but to do it otherwise (without introspection) would be logically impossible.
I would be rather hesitant to do this. Please correct me if I am wrong and then I will delete, but it sounds like you want to maintain an A object along with a B object. If they indeed are not the same object, the "tying together" (that's a scientific term) you'll have to do would be pretty ugly.