Calling super super class method - java

Let's say I have three classes A, B and C.
B extends A
C extends B
All have a public void foo() method defined.
Now from C's foo() method I want to invoke A's foo() method (NOT its parent B's method but the super super class A's method).
I tried super.super.foo();, but it's invalid syntax.
How can I achieve this?

You can't even use reflection. Something like
Class superSuperClass = this.getClass().getSuperclass().getSuperclass();
superSuperClass.getMethod("foo").invoke(this);
would lead to an InvocationTargetException, because even if you call the foo-Method on the superSuperClass, it will still use C.foo() when you specify "this" in invoke. This is a consequence from the fact that all Java methods are virtual methods.
It seems you need help from the B class (e.g. by defining a superFoo(){ super.foo(); } method).
That said, it looks like a design problem if you try something like this, so it would be helpful to give us some background: Why you need to do this?

You can't - because it would break encapsulation.
You're able to call your superclass's method because it's assumed that you know what breaks encapsulation in your own class, and avoid that... but you don't know what rules your superclass is enforcing - so you can't just bypass an implementation there.

You can't do it in a simple manner.
This is what I think you can do:
Have a bool in your class B. Now you must call B's foo from C like [super foo] but before doing this set the bool to true. Now in B's foo check if the bool is true then do not execute any steps in that and just call A's foo.
Hope this helps.

To quote a previous answer "You can't - because it would break encapsulation." to which I would like to add that:
However there is a corner case where you can,namely if the method is static (public or protected). You can not overwrite the static method.
Having a public static method is trivial to prove that you can indeed do this.
For protected however, you need from inside one of your methods to perform a cast to any superclass in the inheritance path and that superclass method would be called.
This is the corner case I am exploring in my answer:
public class A {
static protected callMe(){
System.out.println("A");
}
}
public class B extends A {
static protected callMe(){
System.out.println("B");
}
}
public class C extends B {
static protected callMe(){
System.out.println("C");
C.callMe();
}
public void accessMyParents(){
A a = (A) this;
a.callMe(); //calling beyond super class
}
}
The answer remains still No, but just wanted to show a case where you can, although it probably wouldn't make any sense and is just an exercise.

Yes you can do it. This is a hack. Try not to design your program like this.
class A
{
public void method()
{ /* Code specific to A */ }
}
class B extends A
{
#Override
public void method()
{
//compares if the calling object is of type C, if yes push the call to the A's method.
if(this.getClass().getName().compareTo("C")==0)
{
super.method();
}
else{ /*Code specific to B*/ }
}
}
class C extends B
{
#Override
public void method()
{
/* I want to use the code specific to A without using B */
super.method();
}
}

There is a workaround that solved my similar problem:
Using the class A, B, and C scenario, there is a method that will not break encapsulation nor does it require to declare class C inside of class B. The workaround is to move class B's methods into a separate but protected method.
Then, if those class B's methods are not required simply override that method but don't use 'super' within that method. Overriding and doing nothing effectively neutralises that class B method.
public class A {
protected void callMe() {
System.out.println("callMe for A");
}
}
public class B extends A {
protected void callMe() {
super.callMe();
methodsForB(); // Class B methods moved out and into it's own method
}
protected void methodsForB() {
System.out.println("methods for B");
}
}
public class C extends B {
public static void main(String[] args) {
new C().callMe();
}
protected void callMe() {
super.callMe();
System.out.println("callMe for C");
}
protected void methodsForB() {
// Do nothing thereby neutralising class B methods
}
}
The result will be:
callMe for A
callMe for C

It's not possible, we're limited to call the superclass implementations only.

I smell something fishy here.
Are you sure you are not just pushing the envelope too far "just because you should be able to do it"? Are you sure this is the best design pattern you can get? Have you tried refactoring it?

I had a problem where a superclass would call an top class method that was overridden.
This was my workaround...
//THIS WOULD FAIL CALLING SUPERCLASS METHODS AS a1() would invoke top class METHOD
class foo1{
public void a1(){
a2();
}
public void a2(){}
}
class foo2 extends foo1{
{
public void a1(){
//some other stuff
super.a1();
}
public void a2(){
//some other stuff
super.a2();
}
//THIS ENSURES THE RIGHT SUPERCLASS METHODS ARE CALLED
//the public methods only call private methods so all public methods can be overridden without effecting the superclass's functionality.
class foo1{
public void a1(){
a3();}
public void a2(){
a3();}
private void a3(){
//super class routine
}
class foo2 extends foo1{
{
public void a1(){
//some other stuff
super.a1();
}
public void a2(){
//some other stuff
super.a2();
}
I hope this helps.
:)

Before using reflection API think about the cost of it.
It is simply easy to do. For instance:
C subclass of B and B subclass of A. Both of three have method methodName() for example.
public abstract class A {
public void methodName() {
System.out.println("Class A");
}
}
public class B extends A {
public void methodName() {
super.methodName();
System.out.println("Class B");
}
// Will call the super methodName
public void hackSuper() {
super.methodName();
}
}
public class C extends B {
public static void main(String[] args) {
A a = new C();
a.methodName();
}
#Override
public void methodName() {
/*super.methodName();*/
hackSuper();
System.out.println("Class C");
}
}
Run class C Output will be:
Class A
Class C
Instead of output:
Class A
Class B
Class C

In my simple case I had to inherit B and C from abstract class, that incapsulates equal methods of B and C. So that
A
|
Abstr
/ \
B C
While it doesn't solve the problem, it can be used in simple cases, when C is similar to B. For instance, when C is initialized, but doesn't want to use initializers of B. Then it simply calls Abstr methods.
This is a common part of B and C:
public abstract class Abstr extends AppCompatActivity {
public void showProgress() {
}
public void hideProgress() {
}
}
This is B, that has it's own method onCreate(), which exists in AppCompatActivity:
public class B extends Abstr {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Call from AppCompatActivity.
setContentView(R.layout.activity_B); // B shows "activity_B" resource.
showProgress();
}
}
C shows its own layout:
public class C extends Abstr {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Call from AppCompatActivity.
setContentView(R.layout.activity_C); // C shows "activity_C" resource.
showProgress();
}
}

This is not something that you should do normally but, in special cases where you have to workaround some bug from a third party library (if it allow to do so), you can achieve calling a super super class method that has already been overwritten using the delegation pattern and an inner class that extends the super super class to use as a bridge:
class A() {
public void foo() {
System.out.println("calling A");
}
}
class B extends A() {
#Overwrite
public void foo() {
System.out.println("calling B");
}
}
class C extends B() {
private final a;
public C() {
this.a = new AExtension();
}
#Overwrite
public void foo() {
a.foo();
}
private class AExtension extends A {
}
}
This way you will be able to not only call the super super method but also combine calls to other super super class methods with calls to methods of the super class or the class itself by using `C.super` or `C.this`.

Related

Calling class's methods into an interface

I have created some interface such that:
public interface A{
}
and i would like to call the method a that I have already implemented in class B in interface A such that:
public class B{
public boolean a(){
return true;
}
}
public interface A{
public void call {
a();
}
}
without any errors, any help please?
What you want to do is strictly speaking impossible, as you cannot define method implementations in an interface. You can get something similar by defining an implementation of the interface that extends B. Hopefully that is close enough.
public class AImplementation extends B implements A{
public void call(){
a();
}
}
If you are using any java version before 8, then stick with the answers of #tinker and #Davis Broda. They provide better design since they do not couple your interface to the B class. If you insist however, in java 8 you can have default method implementations as well as static methods in an interface.
If your method is for inheritance then you have to use a default method. Add the default keyword:
default void call() {
...
}
Now the problem is how to get a reference to the class in order to call the method since you cannot have instance fields in interfaces. You have two choices:
Pass the object of B as a method parameter:
public interface A{
default void call(B b) {
b.a();
}
}
or make the method in B static
public interface A{
default void call() {
B.a();
}
}
If your method is not for inheritance but just a utility than you can make it static as :
public interface A{
public static void call() {
B.a();
}
}
I agree with #Davis Broda's answer, there is no way to have a method definition in an interface. But I have another way to address this.
You can have the interface and then have an abstract class implement this interface, and then have all other classes extend the abstract class. The abstract class doesn't have to extend the class from where you want to call the method, you could call it from an instance of that class too.
public interface A {
void caller();
}
public class B {
public void callMe() {
}
}
public class AbstractA implements A {
private B b;
public AbstractA(B b) {
this.b = b;
}
#Override
public void caller() {
b.callMe();
}
}
This way, all implementations of AbstractA will be able to call B's callMe method. And you can access this directly from the interface using this code:
A anInstance = someInstance;
anInstance.caller();
Your question is not very clear, but if I'm guessing right, you want interface A to be kind of a generic caller.
If you're using Java 8, you can achive that using a method reference:
public class B {
public boolean a() {
return true;
}
}
public interface A<T> {
default T call(Supplier<T> s) {
return s.get();
}
}
public class AImpl
implements A<Boolean> {
}
public class Sample {
public static void main(String[] args) {
AImpl a = new AImpl();
B b = new B();
boolean result = a.call(b::a);
System.out.println(result); // true
}
}
This uses Supplier<T> because your method a() in class B returns a boolean and does not receive any arguments.

Unset variables and methods

I have an abstract class that is extended to provide standard methods and variables that I need.
This time, however, I have to extend the same class but some variables and some methods do not serve me. So I was wondering if it was possible to turn off these variables / methods useless. I specify that I'm forced to extend this class, I can not create another.
For example, i have this abstract class:
public abstract class A {
protected int a, b, c;
public abstract void A();
public abstract void B();
public abstract void C();
}
public class B extends A {
public B() {
a = 5;
b = 7;
A();
B();
}
public void A() {
System.out.println("A: " + a);
}
public void B() {
System.out.println("B: " + b);
}
//Unset the variable 'c' and the method 'C()' because they are useless
}
Actually I do not know if it's worth it to do it, I rely on your knowledge.
This is bad behavior and it is advised to split your class hierarchy by pulling the common members of A and B in a new abstract super class and letting the rest which is specific to the class hierarchy of A in A.
This leeds to a situation similar to
public abstract class BaseClass {
protected int a, b;
public abstract void A();
public abstract void B();
}
public abstract class A extends BaseClass {
protected int c;
public abstract void C();
}
public class B extends BaseClass {
}
There is no built-in mechanism to 'unset' a variable or a method of a superclass.
The standard solution is to create two base class.
public abstract class A {
protected int a, b;
public abstract void A();
public abstract void B();
}
public abstract class AC extends A {
protected int c;
public abstract void C();
}
A (terrible) workaround, which only works with method, could be to implement something like the below code to forbid the use of C().
#Override
public void C() {
throw new UnsupportedOperationException("This method is not allowed for this class");
}
Long story short, javac will accept the use C(), but a RuntimeException will be released on runtime. This exception will produce a crash if not catched, but because of the nature of RuntimeException, the compiler doesn't need a try statement...
Well, that's just an ugly piece of code =P
A cleaner workaround was proposed by Nick L. on another response, consisting to set C() as private.
As mentioned before, this is bad design. If there are methods/fields that are not going to be needed in derived classed, then you should put them in another abstract class and derives the previous one.
As a workaround, I think you can set as private the function you want to be publicly inaccessible in B class if you want it not to be abstract:
public class B extends A {
//c property is private.
public B() {
a = 5;
b = 7;
A();
B();
}
public void A() {
System.out.println("A: " + a);
}
public void B() {
System.out.println("B: " + b);
}
//This is set as publicly inaccessible, although implementation is provided.
private void C() {}
}
Only way you can do is make method c as abstract. So no need of implementation. if you need this in later sub classes you can use it
public abstract void C();

Overriding a base class method in a derived class

I have a base class A, having a method "say" that calls from constructor of A. All the heritable classes uses the method "say" like it is. But one of the classes need to redefine this method. How is it possible?
For sure, I can denote base method "say" as abstract, but in that way, i have to copy the same method "say" in all the heritable classes.
If i just redefine method without denoting base one as abstract, it is not gonna be called.
public abstract class A(){
public A(){
say(); // <- wanna call this method from heritable class, if its redefined.
}
protected void say(){};
}
public class B extends A(){
public B(){
super();
}
private void say(){};
}
refactoring 1
public abstract class A(){
public A(){
// constructor methods
}
protected void say(){};
protected void executeSay(){
say();
}
}
public class B extends A(){
public B(){
super();
executeSay();
}
#Override
protected void say(){};
}
First of all one must be made clear: calling an overridable method from a constructor is a well-known antipattern. It will almost certainly break your code because the subclass method will be invoked before the subclass constructor is done and so will observe an uninitialized object. Thus I should better refrain from giving you detailed advice on Java technicalities involved in achieving this antipattern.
The only safe way to acomplish your requirement is to let the construction finish and only afterwards call an initialize-kind of method. If you want to ensure initialize is always invoked, make the constructors non-public and provide a factory method instead.
Unfortunately, Java requires quite a bit of work on your part to make this work properly.
You cannot instantiate a abstract class. That saying you have to link the abstract class reference to the concrete inherited class.
eg. A a = new B();
If that's the case, and B have redefined the say() method, then the say method in B will be called.
public class TestPad {
public static void main(String[] args) {
A a = new B();
}
}
abstract class A {
public A() {
say();
}
public void say(){
System.out.println("A");
};
}
class B extends A {
public B() {
super();
}
public void say() {
System.out.println("B");
}
}
The output will be B
public class B extends A {
public B() {
super();
}
#Override
protected void say() {
// your diffent say code
};
}
I'm not sure if you are allowed to reduce visibility to private.
Because of polymorphic method invocation, in your case the B.say() will be invoked if you override it.
But as #sanbhat commented, you need to change visibility of say() to protected.

Inheritance and Private Methods

Given the following block of code:
public class Trial {
public static void main (String[] args){
B obj = new B();
obj.doMethod(); #prints "From A".
}
}
class A {
private void method(){System.out.print("from A");}
public void doMethod(){method();}
}
class B extends A {
public void method(){System.out.print("from B");}
public void doMethod(){super.doMethod();}
}
It turns out that the method() from class A is invoked. Why is this?
You explicitly implement it that way. super calls method from base class which is A
public void doMethod(){super.doMethod();}
So the method chaining is like this:
B.doMethod() -> A.doMethod() -> A.method() -> "from A"
I think your question is if in class A private void method(){System.out.print("from A");} is private then why is printing "from A" in class B.
Answer is very simple you can't call method() of A class form any other class .But you can call it with object of its own.
when you calls super.doMethod(); then its function of super and method() is its own method so it can call it.
Because, see below:
class B extends A {
public void method(){System.out.print("from B");}
public void doMethod(){super.doMethod();}
}
Here in Class B's doMethod() you're invoiking Class A's doMethod() using super.doMethod(). So obviously it's printing Class A's doMethod().
You call the doMethod with super keyword. It's means it will call parent implementation
More on super keyword
Your code gives simple object creation (B obj = new B();) and a call using super. Super is used like other people mentioned for parent class. Things could have been different if you try something like (A obj = new B();), which is more interesting.
method() in class A is private and private methods can't be overriden. And when overriding it's better to use #Override annotion.
class B extends A {
#Override
public void method(){System.out.print("from B");} // Compile error
}
A similar thing happens, if you change the method to a static method.
class A {
public static void method(){System.out.print("from A");}
}
class B extends A {
public static void method(){System.out.print("from B");}
}

OOP: How to force extending class to supply private method?

Example : How would I make furtherSpecificProcessing method a private method?
Reason: I would like to be able to new an object of type B or C and only have doStuff() visible to programmer. while at the same time class B and C supply the additional functionality
abstract class A
{
protected abstract void furtherSpecificProcessing();
//concrete method utilizing abstract method
public void doStuff()
{
//busy code
furtherSpecificProcessing();
//more busy code
}
public class B extends A
{
public void furtherSpecificProcessing
{
//Class B specific processing
}
}
public class C extends A
{
public void furtherSpecificProcessing
{
//Class C specific processing
}
}
I don't think you can force return type to be private for overriding method.
Access Must not be more restrictive. Can be less restrictive.
I would suggest reading method overriding rules.
Override furtherSpecificProcessing() as protected, not as public in extending classes.
Declare the method as protected instead of public in both classes B and C.
Than what you need will work :
B b = new B();
b.doStuff(); // Will do stuff
b.furtherSpecificProcessing(); // Will not compile
and the same goes for instances of class C

Categories

Resources