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();
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.
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.
I'm trying to make a spcial add-ons for my application. I need to override some methods of a class without editing the class file.
Here is a scheme:
class A
{
public void method1()
{
// Do something here
}
public int method2()
{
// Do something
}
}
Now from my class B, I want to override the method1 func from the class A, and force the A class to use my new method.
class B
{
public void method1()
{
Do something
}
}
I want to update my class A code without editing the A class. Is that possible?
Thanks.
use class B extends A and ovverride method that you want to change. how ever you have to use instance of class B not A. like
class B extends A
{
public void method1(){
Do something
}
}
A a = new B();
a.method1();
Sounds like proxy can solve your problem. Take a look at cglib
Enhancer e = new Enhancer();
e.setSuperclass(A.class);
e.setCallback(new MyCallback());
A proxied = e.create();
And here is sample impl of MyCallback class...
class MyCallback implements MethodInterceptor{
public Object intercept(Object obj,
Method method,
Object[] args,
MethodProxy proxy){
Object stuffToReturn = null;
if ("method1".equals(method.getName()) {
//Class B's method1 impl
} else {
//call the original method in class A
stuffToReturn = method.invoke(proxy, args);
}
return stuffToReturn;
}
}
Not if you create your objects using A constructor.
You could have B extend A, but you will have to instantiate objects as new B() (even if you can declare them as A, as in A obj = new B()).
No, in languages like Java this is not possible directly. new A will always create at runtime an instance of A, not of a derived B.
If it's possible (that is, if you control all the code which instantiates A), you can use some clumsy workarounds introducing a kind of indirection. For example, you can have a configurable factory producing As (which will on demand switch to producing Bs under the cover) -- this seems to be the Java way. (You'll need all the code construct As not directly, but through the factory.)
If I am not mistaken, the feature you are looking for is available in Objective C out of the box -- but not in Java.
By inheritance, yes. Simply change the class B definition : class B extends A
This has no sense. Overriding means precisely to re-define a method that is inherited from a super class. So here are some solutions :
B must extend A and then you can override one of the methods of A. Give it the same signature as in A, use the #Override annotation to be sure.
A has some dependency that is injected : method1 and method2 use some tierce object (C) to get the job done and the dependency is injected in A. Then B can use a A with custom C object that suits its needs. Most of code of A won't change that way.
One way to achieve this would be to use some sort of factory instance to create objects of type A instead of invoking the A() constructor directly in your code. Your add-on would then need to provide and register its own implementation of this factory which would create instances of class B. This only works if the add-on gets loaded and initialized before any instances of A were created.
Another approach would be to implement your own ClassLoader and use this to modify the bytecode of class A at loading time. You could search for tools for aspect oriented programming to implement this. This is only possible if you have control over the class loading process of class A.
No, you can't do that, it's impossible to modify the behavior of a class without actually modifying the class, however, there is a workaround:
B should be inherited from A. This is absolutely needed. A won't change, but its children classes might change in behavior
Overwrite method1() and method2()
Suppose you have an a object of the A class. If you convert it to B, its behavior will be your new, custom behavior.
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.