I have a class C1:
public class C1 {
public void method() {
//Do something
}
protected void anotherMethod() {
if (something) {
method();
/*Here, I want to call the method C1.method,
* but C2.method is called
*/
}
}
}
and another class C2 that extends it and overrides the method:
public class C2 extends C1 {
#Override
public void method() {
if (something) {
anotherMethod();
} else {
super.method();
}
}
}
My problem is described in the code comment. I can't run parent method in the parent class. What is the reason?
Annoyingly, you can't (setting aside reflective hacks).
But you could do something on the lines
public class C1 {
public final void _method() /*rename to taste*/{
}
public void method(){
_method();
}
}
and override method in your derived class. If you specifically require the base class method, then call _method(). I think that's the nearest to writing C1::method() which is permissible in C++.
As far as your C2 class is concerned the anotherMethod() is not overriden so it calls its own method() if something is true.
Override it as follows:
#Override
protected void anotherMethod() {
if (something) {
super.method(); //Here, I want to call the method `C1.method`, but `C2.method` is called
}
}
to call the parent method from child's anotherMethod() definition.
Related
I have an enum that contains an non-public abstract method and I can not change the visibility of this abstract method. The abstract method is implemented for every single unit inside the enum.
I am trying to access this method from another package for the purposes of unit testing, but I can not because it is not visible in the other package. Is there a way where I can create a getter method for an abstract method?
Is there a different way to do the unit test in a way that does not involve using a getter method or changing the visibility of the abstract method?
Here is an example of the code I am working with:
public enum random {
A{
someFunction() {
System.out.println("A");
}
}
B{
someFunction() {
System.out.println("B");
}
}
C{
someFunction() {
System.out.println("C");
}
}
abstract void someFunction();
};
There are two ways you can do this. One way, like you suggested in your question, is to use a public method to expose your package-private method. Here's a short example of such a program:
public enum MyEnum {
A {
#Override
void someFunction() {
System.out.println("A");
}
},
B {
#Override
void someFunction() {
System.out.println("B");
}
},
C {
#Override
void someFunction() {
System.out.println("C");
}
};
abstract void someFunction();
public void someFunctionPublic() {
// Here I'm just calling the package-private method from a public method:
someFunction();
}
}
public class Other {
public static void main(String[] args) {
// Here I call my public method:
MyEnum.A.someFunctionPublic();
}
}
Output will be:
A
The other way is to use something called reflection. You mentioned that you wanted a way to access the method without creating a getter method. This is how you can do just that:
// This is exactly how you had it, no changes:
public enum MyEnum {
A {
#Override
void someFunction() {
System.out.println("A");
}
},
B {
#Override
void someFunction() {
System.out.println("B");
}
},
C {
#Override
void someFunction() {
System.out.println("C");
}
};
abstract void someFunction();
}
public class Other {
// Note the throws clauses, this is important because I call methods that throw checked exceptions:
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
// Get a handle on the method:
Method method = MyEnum.class.getDeclaredMethod("someFunction");
// Set it to be accessible (since you specified it to be package-private):
method.setAccessible(true);
// Invoke it using the implementation in MyEnum.A:
method.invoke(MyEnum.A);
}
}
Output will be:
A
Please note that reflection can get out of hand quite quickly, especially if you start renaming methods and/or changing the method headers. Useful for testing, yes, but I would keep it out of production code. Also, a small terminology thing, you refer to "methods" as "functions" in your question. A method is a function that belongs to an Object, so since Java is entirely object-oriented, there are no functions in Java.
I am trying to find the most elegant way to allow a child and parent to react to an event initiated by the grandparent. Here's a naive solution to this:
abstract class A {
final public void foo() {
// Some stuff here
onFoo();
}
protected abstract void onFoo();
}
abstract class B extends A {
#Override
final protected void onFoo() {
// More stuff here
onOnFoo();
}
protected abstract void onOnFoo();
}
class C extends B {
#Override
protected void onOnFoo() {
// Even more stuff here
}
}
So basically, I'm trying to find the best way to allow all related classes to perform some logic when foo() is called. For stability and simplicity purposes I prefer if it is all done in order, although it's not a requirement.
One other solution I found involves storing all the event handlers as some form of Runnable:
abstract class A {
private ArrayList<Runnable> fooHandlers = new ArrayList<>();
final public void foo() {
// Some stuff here
for(Runnable handler : fooHandlers) handler.run();
}
final protected void addFooHandler(Runnable handler) {
fooHandlers.add(handler);
}
}
abstract class B extends A {
public B() {
addFooHandler(this::onFoo);
}
private void onFoo() {
// Stuff
}
}
class C extends B {
public C() {
addFooHandler(this::onFoo);
}
private void onFoo() {
// More stuff
}
}
This method is certainly preferable to the first. However I am still curious if there is a better option.
Have you considered the Template Method pattern? It works well to define a high level method that delegates to derived types to fill-in the gaps.
What about this by calling the super method?
class A {
void foo() {
System.out.println("Some stuff here");
}
}
class B extends A {
#Override
void foo() {
super.foo();
System.out.println("More stuff here");
}
}
class C extends B {
#Override
void foo() {
super.foo();
System.out.println("Even more stuff here");
}
}
I have an abstract class Task with two methods execute() and finish() as the following:
abstract class Task {
abstract void execute();
private void finish() {
// Do something...
}
}
How can I ensure that the overloaded method execute() in subclasses of Task implicitly calls finish() as the last statement?
I don't believe there is any way of 'forcing' sub-classes to invoke a method but you could try some sort of template method approach:
abstract class Foo {
protected abstract void bar(); // <--- Note protected so only visible to this and sub-classes
private void qux() {
// Do something...
}
// This is the `public` template API, you might want this to be final
public final void method() {
bar();
qux();
}
}
The public method is the entry-point and invokes the abstract bar and then the private qux method, this means that any sub-classes follow the template pattern. However it's no panacea of course - a sub-class could simply ignore the public method.
You can create a ExecutorCloseable class that implements the [AutoCloseable] interface, such as:
public class ExecutorCloseable extends Foo implements AutoCloseable
{
#Override
public void execute()
{
// ...
}
#Override //this one comes from AutoCloseable
public void close() //<--will be called after execute is finished
{
super.finish();
}
}
You could call it this way (silly main() example):
public static void main(String[] args)
{
try (ExecutorCloseable ec = new ExecutorCloseable ())
{
ec.execute();
} catch(Exception e){
//...
} finally {
//...
}
}
Hope it makes sense, I can't really know how you call these methods nor how you create the classes. But hey, it's a try : )
For this to work, the finish() method on Foo should be protected or public (first one recommended), though.
I have class Dad with subclass Son. I'd like to create a subclass of Dad and a subclass of Son that overrides a method of Dad.
What would be the best way of doing this without repeating code? I can not modify Dad and Son.
Given...
public class Dad {
public void doSomething() {}
}
public class Son extends Dad {
}
...I'd like to create...
public class DadSubclass extends Dad {
#Overrides
public void doSomething() {
// My code
}
}
public class SonSubclass extends Son {
#Overrides
public void doSomething() {
// My code
}
}
...without repeating // My code.
The obvious solution would be to create a helper class and call it for both, but this is problematic if I want to call protected methods, and I'm not allowed to create the subclasses with the same package.
Is there a better solution?
Create a common helper class and call it.
Assuming your code isn't accessing member variables, I would just put this code in a static utility class. If this isn't the case, you can still do this by passing in a common superclass - that of 'Dad' public static void mycode(Dad d). If you need specific variables in the subclasses themselves, I would rethink your class structure.
What you really want here is something like this:
class DadSonSubclass extends Dad, Son {
public void doSomething() {
//mycode
}
}
This is multiple inheritance, which is not supported by Java. So your only option would be to create a helper/utility class, which is perfectly acceptable. If you need to call protected methods, just pass the Dad object in to the helper class and create public callback methods to access this info.
Maybe better, maybe not, depending on your point of view, but it can certainly be done. Put your code into a helper class, and use a callback to give that helper access to the protected methods it needs:
interface Callback {
void foo();
void bar();
void one();
void two();
}
class Helper {
static void helpMe(Callback callback) {
// My code
}
}
class DadSubclass extends Dad {
#Override
public void doSomething() {
Helper.helpMe(new Callback() {
public void foo() {
DadSubclass.this.foo();
}
public void bar() {
DadSubclass.this.bar();
}
public void one() {
throw new UnsupportedOperationException("one() doesn't exist in Dad");
}
public void two() {
throw new UnsupportedOperationException("two() doesn't exist in Dad");
}
});
}
}
class SonSubclass extends Son {
#Override
public void doSomething() {
Helper.helpMe(new Callback() {
public void foo() {
SonSubclass.this.foo();
}
public void bar() {
SonSubclass.this.bar();
}
public void one() {
SonSubclass.this.one();
}
public void two() {
SonSubclass.this.two();
}
});
}
}
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`.