Automatically delegating all methods of a java class - java

Say I have a class with many of public methods:
public class MyClass {
public void method1() {}
public void method2() {}
(...)
public void methodN() {}
}
Now I would like to create a wrapper class which would delegate all the methods to wrapped instance (delegate):
public class WrapperClass extends MyClass {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
public void method1() { delegate.method1(); }
public void method2() { delegate.method2(); }
(...)
public void methodN() { delegate.methodN(); }
}
Now if MyClass has a lot of methods I would need to override each of them which is more or less the same code which just "delegates". I was wondering if it is possible to do some magic to automatically call a method in Java (so the Wrapper class would need to say "Hey if you call a method on me just go to delegate object and call this method on it).
BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final).
NOTE: I do not want IDE generation. I know I can do it with help of IntelliJ/Eclipse, but I'm curious if this can be done in code.
Any suggestions how to achieve something like this? (NOTE: I would probably be able to do it in some scripting languages like php where I could use php magic functions to intercept the call).

Perhaps the dynamic Proxy of java can help you. It only works if you consequently use interfaces. In this case, I will call the interface MyInterface and set up a default implementation:
public class MyClass implements MyInterface {
#Override
public void method1() {
System.out.println("foo1");
}
#Override
public void method2() {
System.out.println("foo2");
}
#Override
public void methodN() {
System.out.println("fooN");
}
public static void main(String[] args) {
MyClass wrapped = new MyClass();
wrapped.method1();
wrapped.method2();
MyInterface wrapper = WrapperClass.wrap(wrapped);
wrapper.method1();
wrapper.method2();
}
}
The wrapper class implementation would look like:
public class WrapperClass extends MyClass implements MyInterface, InvocationHandler {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delegate = delegate;
}
public static MyInterface wrap(MyClass wrapped) {
return (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class[] { MyInterface.class }, new WrapperClass(wrapped));
}
//you may skip this definition, it is only for demonstration
public void method1() {
System.out.println("bar");
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = findMethod(this.getClass(), method);
if (m != null) {
return m.invoke(this, args);
}
m = findMethod(delegate.getClass(), method);
if (m != null) {
return m.invoke(delegate, args);
}
return null;
}
private Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Note that this class:
extends MyClass, to inherit a default implementation (any other would do)
implements Invocationhandler, to allow the proxy to do reflection
optionally implement MyInterface (to satisfy the decorator pattern)
This solution allows you to override special methods, but to delegate all others. This will even work with sub classes of Wrapper class.
Note that the method findMethod does not yet capture the special cases.

This question is 6 months old already and #CoronA's wonderful answer has satisfied and been accepted by #walkeros, but I thought I would add something here as I think this can be pushed an extra step.
As discussed with #CoronA in the comments to his answer, instead of having to create and maintain a long list of MyClass methods in WrapperClass (i.e. public void methodN() { delegate.methodN(); }), the dynamic proxy solution moves this to the interface. The issue is that you still have to create and maintain a long list of signatures for the MyClass methods in the interface, which is perhaps a bit simpler but doesn't completely solve the problem. This is especially the case if you don't have access to MyClass in order to know all the methods.
According to Three approaches for decorating your code,
For longer classes, a programmer must choose the lesser of two evils:
implement many wrapper methods and keep the type of decorated object
or maintain a simple decorator implementation and sacrifice retaining
the decorated object type.
So perhaps this is an expected limitation of the Decorator Pattern.
#Mark-Bramnik, however, gives an fascinating solution using CGLIB at Interposing on Java Class Methods (without interfaces). I was able to combine this with #CoronaA's solution in order to create a wrapper that can override individual methods but then pass everything else to the wrapped object without requiring an interface.
Here is MyClass.
public class MyClass {
public void method1() { System.out.println("This is method 1 - " + this); }
public void method2() { System.out.println("This is method 2 - " + this); }
public void method3() { System.out.println("This is method 3 - " + this); }
public void methodN() { System.out.println("This is method N - " + this); }
}
Here is WrapperClass which only overrides method2(). As you'll see below, the non-overridden methods are, in fact, not passed to the delegate, which can be a problem.
public class WrapperClass extends MyClass {
private MyClass delagate;
public WrapperClass(MyClass delegate) { this.delagate = delegate; }
#Override
public void method2() {
System.out.println("This is overridden method 2 - " + delagate);
}
}
Here is MyInterceptor which extends MyClass. It employs the proxy solution using CGLIB as described by #Mark-Bramnik. It also employs #CononA's method of determining whether or not to send the method to the wrapper (if it is overridden) or the wrapped object (if it is not).
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyInterceptor extends MyClass implements MethodInterceptor {
private Object realObj;
public MyInterceptor(Object obj) { this.realObj = obj; }
#Override
public void method2() {
System.out.println("This is overridden method 2 - " + realObj);
}
#Override
public Object intercept(Object arg0, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
Method m = findMethod(this.getClass(), method);
if (m != null) { return m.invoke(this, objects); }
Object res = method.invoke(realObj, objects);
return res;
}
private Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Here is Main and the results you get if you run it.
import net.sf.cglib.proxy.Enhancer;
public class Main {
private static MyClass unwrapped;
private static WrapperClass wrapped;
private static MyClass proxified;
public static void main(String[] args) {
unwrapped = new MyClass();
System.out.println(">>> Methods from the unwrapped object:");
unwrapped.method1();
unwrapped.method2();
unwrapped.method3();
wrapped = new WrapperClass(unwrapped);
System.out.println(">>> Methods from the wrapped object:");
wrapped.method1();
wrapped.method2();
wrapped.method3();
proxified = createProxy(unwrapped);
System.out.println(">>> Methods from the proxy object:");
proxified.method1();
proxified.method2();
proxified.method3();
}
#SuppressWarnings("unchecked")
public static <T> T createProxy(T obj) {
Enhancer e = new Enhancer();
e.setSuperclass(obj.getClass());
e.setCallback(new MyInterceptor(obj));
T proxifiedObj = (T) e.create();
return proxifiedObj;
}
}
>>> Methods from the unwrapped object:
This is method 1 - MyClass#e26db62
This is method 2 - MyClass#e26db62
This is method 3 - MyClass#e26db62
>>> Methods from the wrapped object:
This is method 1 - WrapperClass#7b7035c6
This is overridden method 2 - MyClass#e26db62
This is method 3 - WrapperClass#7b7035c6
>>> Methods from the proxy object:
This is method 1 - MyClass#e26db62
This is overridden method 2 - MyClass#e26db62
This is method 3 - MyClass#e26db62
As you can see, when you run the methods on wrapped you get the wrapper for the methods that are not overridden (i.e. method1() and method3()). When you run the methods on proxified, however, all of the methods are run on the wrapped object without the pain of having to delegate them all in WrapperClass or put all of the method signatures in an interface. Thanks to #CoronA and #Mark-Bramnik for what seems like a pretty cool solution to this problem.

Check the #Delegate annotation from Lombok framework:
https://projectlombok.org/features/Delegate.html

Switch to Groovy :-)
#CompileStatic
public class WrapperClass extends MyClass {
#Delegate private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
//Done. That's it.
}
http://mrhaki.blogspot.com/2009/08/groovy-goodness-delegate-to-simplify.html

You don't have to do this -- your Wrapper class is a subclass of the original class, so it inherits all of its publicly accessible methods -- and if you don't implement them, the original method will be called.
You shouldn't have extends Myclass together with a private MyClass object -- that's really really redundant, and I can't think of a design pattern where doing that is right. Your WrapperClass is a MyClass, and hence you can just use its own fields and methods instead of calling delegate.
EDIT: In the case of MyClass being final, you'd be circumventing the willfull declaration to not allow subclassing by "faking" inheritance; I can't think of anyone willing to do that other than you, who is in control of WrapperClass; but, since you're in control of WrapperClass, not wrapping everything you don't need is really more than an option -- it's the right thing to do, because your object is not a MyClass, and should only behave like one in the cases you mentally considered.
EDIT you've just changed your question to mean something completely different by removing the MyClass superclass to your WrapperClass; that's a bit bad, because it invalidates all answers given so far. You should have opened another question.

Credits go to CoronA for Pointing out the Proxy and InvocationHandler classes. I worked out a more reusable utility class based on his solution, using generics:
public class DelegationUtils {
public static <I> I wrap(Class<I> iface, I wrapped) {
return wrapInternally(iface, wrapped, new SimpleDecorator(wrapped));
}
private static <I> I wrapInternally (Class<I> iface, I wrapped, InvocationHandler handler) {
return (I) Proxy.newProxyInstance(wrapped.getClass().getClassLoader(), new Class[] { iface }, handler);
}
private static class SimpleDecorator<T> implements InvocationHandler {
private final T delegate;
private SimpleDecorator(T delegate) {
this.delegate = delegate;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = findMethod(delegate.getClass(), method);
if (m == null) {
throw new NullPointerException("Found no method " + method + " in delegate: " + delegate);
}
return m.invoke(delegate, args);
}
}
private static Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Test it:
public class Test {
public interface Test {
public void sayHello ();
}
public static class TestImpl implements Test {
#Override
public void sayHello() {
System.out.println("HELLO!");
}
}
public static void main(String[] args) {
Test proxy = DelegationUtils.wrap(Test.class, new TestImpl());
proxy.sayHello();
}
}
I wanted to create an automatic delegation class that executes the delegatee's methods on the EDT. With this class, you just create a new utility method that will use an EDTDecorator, in which the implementation will wrap m.invoke in a SwingUtilities.invokeLater.
However, if I reflect on this, I may want to reconsider making a non-Reflection based proxy per interface that I have - it might be cleaner and faster, and more understandable. But, it's possible.

Define a method in WrapperClass i.e. delegate() that returns the instance of MyClass
OR
You can use reflection to do that but the caller has to pass the method name as an argument to an exposed method. And there will be complications regarding the method arguments/overloaded methods etc.
BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final)
The code that you have posted has public class WrapperClass extends MyClass
Actually your current implementation of WrapperClass is actually a decorator on top of MyClass

Let me redefine the problem for a specific case.
I want to override the close method of ResultSet interface in jdbc. My aim is to close the preparedstatement in close method of result set. I could not access to the Class (DelegatingResultSet) that implements in ResultSet interface. There are a lot of methods in ResultSet interface and overriding them one by one and calling the corresponding method from the ResultSet object is one solution. For a dynamic solution I used Dynamic ProxyClasses (https://docs.oracle.com/javase/1.5.0/docs/guide/reflection/proxy.html).
// New ResultSet implementation
public class MyResultSet implements InvocationHandler {
ResultSet rs;
PreparedStatement ps;
private Method closeMethod;
public MyResultSet(ResultSet rs, PreparedStatement ps) {
super();
this.rs = rs;
this.ps = ps;
try {
closeMethod = ResultSet.class.getMethod("close",null);
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
public void close() {
try {
rs.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Object newInstance(ResultSet rs, PreparedStatement ps) {
return java.lang.reflect.Proxy.newProxyInstance(rs.getClass().getClassLoader(), rs.getClass().getInterfaces(),
new MyResultSet(rs,ps));
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result = null;
try {
Class declaringClass = m.getDeclaringClass();
if (m.getName().compareTo("close")==0) {
close();
} else {
result = m.invoke(rs, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
}
return result;
}
}
// How to call it:
ResultSet prs = (ResultSet) MyResultSet.newInstance(rs,ps);

I really appreciated #CoronA's answer. I also looked at #Mark Cramer's answer, but, if I'm not missing something, I think that there are always at least two instances of the "proxified" class with a strange relationship beteen the two objects.
This, along with the fact that cglib is now deprecated, pushed me to find a new implementation based on ByteBuddy.
This is what I came up with:
public class MyClass {
public String testMethod() {
return "11111";
}
public String testMethod2() {
return "aaaaa";
}
}
public class MyClassWithDelegate extends MyClass {
private static final Constructor<? extends MyClassWithDelegate> CONSTRUCTOR_WITH_DELEGATE;
static {
Constructor<? extends MyClassWithDelegate> temp = null;
try {
final var instrumentedMyClassWithDelegateType =
new ByteBuddy()
.subclass(MyClassWithDelegate.class)
.method(ElementMatchers.any())
.intercept(MethodDelegation.to(MethodInterceptor.class))
.make()
.load(MyClassWithDelegate.class.getClassLoader())
.getLoaded();
temp = instrumentedMyClassWithDelegateType.getConstructor(MyClass.class);
} catch (final Exception e) {
LOGGER.error("Cannot instrument class {}", MyClassWithDelegate.class, e);
}
CONSTRUCTOR_WITH_DELEGATE = temp;
}
public static MyClassWithDelegate getInstanceWithDelegate(final MyClass myClass) {
try {
return CONSTRUCTOR_WITH_DELEGATE.newInstance(myClass);
} catch (final Exception e) {
LOGGER.error("Cannot get instance of {}", MyClassWithDelegate.class, e);
throw new IllegalStateException();
}
}
private final boolean initialized;
private final MyClass delegate;
public MyClassWithDelegate(final MyClass delegate) {
super();
this.delegate = delegate;
this.initialized = true;
}
public String testMethod() {
return "22222";
}
public static class MethodInterceptor {
#RuntimeType
public static Object intercept(#This final MyClassWithDelegate self,
#Origin final Method method,
#AllArguments final Object[] args,
#SuperMethod final Method superMethod) throws Throwable {
if (!self.initialized || method.getDeclaringClass().equals(MyClassWithDelegate.class)) {
return superMethod.invoke(self, args);
} else {
return method.invoke(self.delegate, args);
}
}
}
}
The initialized field is used to prevent method calls the super constructor from being redirected to the delegate before its assignment (in this case it wouldn't be a problem, but I wanted to create a generic solution).
Every method called on an instance of MyClassWithDelegate will be redirected to the delegate, except from methods declared inside MyClassWithDelegate itself.
In this example, calling testMethod() on an instance of MyClassWithDelegate will return "22222", while testMethod2() will return "aaaaa".
Obviously, the delegation will actually work only if every instance of MyClassWithDelegate is obtained calling the getInstanceWithDelegate factory method.

Related

How to create constructor in java parameterized with class?

I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}

How do I access a superclass method in java if it has already been overridden by a subclass? [duplicate]

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:
#Override
public String toString() {
return super.super.toString();
}
I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.
What do you guys think?
EDIT:
To clarify: yes I know, that's impossible in Java and I don't really miss it. This is nothing I expected to work and was surprised getting a compiler error. I just had the idea and like to discuss it.
It violates encapsulation. You shouldn't be able to bypass the parent class's behaviour. It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's. For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items". It makes sense to have:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
#Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
#Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
That's fine - RedItems can always be confident that the items it contains are all red. Now suppose we were able to call super.super.add():
public class NaughtyItems extends RedItems
{
#Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
Now we could add whatever we like, and the invariant in RedItems is broken.
Does that make sense?
I think Jon Skeet has the correct answer. I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
which produces the output:
x= 3
super.x= 2
((T2)this).x= 2
((T1)this).x= 1
((I)this).x= 0
(example from the JLS)
However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.
I think the following code allow to use super.super...super.method() in most case.
(even if it's uggly to do that)
In short
create temporary instance of ancestor type
copy values of fields from original object to temporary one
invoke target method on temporary object
copy modified values back to original object
Usage :
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}
I don't have enough reputation to comment so I will add this to the other answers.
Jon Skeet answers excellently, with a beautiful example. Matt B has a point: not all superclasses have supers. Your code would break if you called a super of a super that had no super.
Object oriented programming (which Java is) is all about objects, not functions. If you want task oriented programming, choose C++ or something else. If your object doesn't fit in it's super class, then you need to add it to the "grandparent class", create a new class, or find another super it does fit into.
Personally, I have found this limitation to be one of Java's greatest strengths. Code is somewhat rigid compared to other languages I've used, but I always know what to expect. This helps with the "simple and familiar" goal of Java. In my mind, calling super.super is not simple or familiar. Perhaps the developers felt the same?
There's some good reasons to do this. You might have a subclass which has a method which is implemented incorrectly, but the parent method is implemented correctly. Because it belongs to a third party library, you might be unable/unwilling to change the source. In this case, you want to create a subclass but override one method to call the super.super method.
As shown by some other posters, it is possible to do this through reflection, but it should be possible to do something like
(SuperSuperClass this).theMethod();
I'm dealing with this problem right now - the quick fix is to copy and paste the superclass method into the subsubclass method :)
In addition to the very good points that others have made, I think there's another reason: what if the superclass does not have a superclass?
Since every class naturally extends (at least) Object, super.whatever() will always refer to a method in the superclass. But what if your class only extends Object - what would super.super refer to then? How should that behavior be handled - a compiler error, a NullPointer, etc?
I think the primary reason why this is not allowed is that it violates encapsulation, but this might be a small reason too.
I think if you overwrite a method and want to all the super-class version of it (like, say for equals), then you virtually always want to call the direct superclass version first, which one will call its superclass version in turn if it wants.
I think it only makes rarely sense (if at all. i can't think of a case where it does) to call some arbitrary superclass' version of a method. I don't know if that is possible at all in Java. It can be done in C++:
this->ReallyTheBase::foo();
At a guess, because it's not used that often. The only reason I could see using it is if your direct parent has overridden some functionality and you're trying to restore it back to the original.
Which seems to me to be against OO principles, since the class's direct parent should be more closely related to your class than the grandparent is.
Calling of super.super.method() make sense when you can't change code of base class. This often happens when you are extending an existing library.
Ask yourself first, why are you extending that class? If answer is "because I can't change it" then you can create exact package and class in your application, and rewrite naughty method or create delegate:
package com.company.application;
public class OneYouWantExtend extends OneThatContainsDesiredMethod {
// one way is to rewrite method() to call super.method() only or
// to doStuff() and then call super.method()
public void method() {
if (isDoStuff()) {
// do stuff
}
super.method();
}
protected abstract boolean isDoStuff();
// second way is to define methodDelegate() that will call hidden super.method()
public void methodDelegate() {
super.method();
}
...
}
public class OneThatContainsDesiredMethod {
public void method() {...}
...
}
For instance, you can create org.springframework.test.context.junit4.SpringJUnit4ClassRunner class in your application so this class should be loaded before the real one from jar. Then rewrite methods or constructors.
Attention: This is absolute hack, and it is highly NOT recommended to use but it's WORKING! Using of this approach is dangerous because of possible issues with class loaders. Also this may cause issues each time you will update library that contains overwritten class.
#Jon Skeet Nice explanation.
IMO if some one wants to call super.super method then one must be want to ignore the behavior of immediate parent, but want to access the grand parent behavior.
This can be achieved through instance Of. As below code
public class A {
protected void printClass() {
System.out.println("In A Class");
}
}
public class B extends A {
#Override
protected void printClass() {
if (!(this instanceof C)) {
System.out.println("In B Class");
}
super.printClass();
}
}
public class C extends B {
#Override
protected void printClass() {
System.out.println("In C Class");
super.printClass();
}
}
Here is driver class,
public class Driver {
public static void main(String[] args) {
C c = new C();
c.printClass();
}
}
Output of this will be
In C Class
In A Class
Class B printClass behavior will be ignored in this case.
I am not sure about is this a ideal or good practice to achieve super.super, but still it is working.
Look at this Github project, especially the objectHandle variable. This project shows how to actually and accurately call the grandparent method on a grandchild.
Just in case the link gets broken, here is the code:
import lombok.val;
import org.junit.Assert;
import org.junit.Test;
import java.lang.invoke.*;
/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
return (MethodHandles.Lookup) field.get(null);
}
#Test
public void test() throws Throwable {
val lookup = getImplLookup();
val baseHandle = lookup.findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Sub.class);
val objectHandle = lookup.findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
// Must use Base.class here for this reference to call Object's toString
Base.class);
val sub = new Sub();
Assert.assertEquals("Sub", sub.toString());
Assert.assertEquals("Base", baseHandle.invoke(sub));
Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
}
private static String toString(Object o) {
return o.getClass().getName() + "#" + Integer.toHexString(o.hashCode());
}
public class Sub extends Base {
#Override
public String toString() {
return "Sub";
}
}
public class Base {
#Override
public String toString() {
return "Base";
}
}
}
Happy Coding!!!!
I would put the super.super method body in another method, if possible
class SuperSuperClass {
public String toString() {
return DescribeMe();
}
protected String DescribeMe() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return "I am super";
}
}
class ChildClass extends SuperClass {
public String toString() {
return DescribeMe();
}
}
Or if you cannot change the super-super class, you can try this:
class SuperSuperClass {
public String toString() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return DescribeMe(super.toString());
}
protected String DescribeMe(string fromSuper) {
return "I am super";
}
}
class ChildClass extends SuperClass {
protected String DescribeMe(string fromSuper) {
return fromSuper;
}
}
In both cases, the
new ChildClass().toString();
results to "I am super super"
It would seem to be possible to at least get the class of the superclass's superclass, though not necessarily the instance of it, using reflection; if this might be useful, please consider the Javadoc at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()
public class A {
#Override
public String toString() {
return "A";
}
}
public class B extends A {
#Override
public String toString() {
return "B";
}
}
public class C extends B {
#Override
public String toString() {
return "C";
}
}
public class D extends C {
#Override
public String toString() {
String result = "";
try {
result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
} catch (InstantiationException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}
public class Main {
public static void main(String... args) {
D d = new D();
System.out.println(d);
}
}
run:
A
BUILD SUCCESSFUL (total time: 0 seconds)
I have had situations like these when the architecture is to build common functionality in a common CustomBaseClass which implements on behalf of several derived classes.
However, we need to circumvent common logic for specific method for a specific derived class. In such cases, we must use a super.super.methodX implementation.
We achieve this by introducing a boolean member in the CustomBaseClass, which can be used to selectively defer custom implementation and yield to default framework implementation where desirable.
...
FrameworkBaseClass (....) extends...
{
methodA(...){...}
methodB(...){...}
...
methodX(...)
...
methodN(...){...}
}
/* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
CustomBaseClass(...) extends FrameworkBaseClass
{
private boolean skipMethodX=false;
/* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/
methodA(...){...}
methodB(...){...}
...
methodN(...){...}
methodX(...){
if (isSkipMethodX()) {
setSKipMethodX(false);
super.methodX(...);
return;
}
... //common method logic
}
}
DerivedClass1(...) extends CustomBaseClass
DerivedClass2(...) extends CustomBaseClass
...
DerivedClassN(...) extends CustomBaseClass...
DerivedClassX(...) extends CustomBaseClass...
{
methodX(...){
super.setSKipMethodX(true);
super.methodX(...);
}
}
However, with good architecture principles followed in framework as well as app, we could avoid such situations easily, by using hasA approach, instead of isA approach. But at all times it is not very practical to expect well designed architecture in place, and hence the need to get away from solid design principles and introduce hacks like this.
Just my 2 cents...
IMO, it's a clean way to achieve super.super.sayYourName() behavior in Java.
public class GrandMa {
public void sayYourName(){
System.out.println("Grandma Fedora");
}
}
public class Mama extends GrandMa {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName();
}else {
System.out.println("Mama Stephanida");
}
}
}
public class Daughter extends Mama {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName(lie);
}else {
System.out.println("Little girl Masha");
}
}
}
public class TestDaughter {
public static void main(String[] args){
Daughter d = new Daughter();
System.out.print("Request to lie: d.sayYourName(true) returns ");
d.sayYourName(true);
System.out.print("Request not to lie: d.sayYourName(false) returns ");
d.sayYourName(false);
}
}
Output:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
I think this is a problem that breaks the inheritance agreement.
By extending a class you obey / agree its behavior, features
Whilst when calling super.super.method(), you want to break your own obedience agreement.
You just cannot cherry pick from the super class.
However, there may happen situations when you feel the need to call super.super.method() - usually a bad design sign, in your code or in the code you inherit !
If the super and super super classes cannot be refactored (some legacy code), then opt for composition over inheritance.
Encapsulation breaking is when you #Override some methods by breaking the encapsulated code.
The methods designed not to be overridden are marked
final.
In C# you can call a method of any ancestor like this:
public class A
internal virtual void foo()
...
public class B : A
public new void foo()
...
public class C : B
public new void foo() {
(this as A).foo();
}
Also you can do this in Delphi:
type
A=class
procedure foo;
...
B=class(A)
procedure foo; override;
...
C=class(B)
procedure foo; override;
...
A(objC).foo();
But in Java you can do such focus only by some gear. One possible way is:
class A {
int y=10;
void foo(Class X) throws Exception {
if(X!=A.class)
throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
y++;
System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
}
void foo() throws Exception {
System.out.printf("A.foo()\n");
this.foo(this.getClass());
}
}
class B extends A {
int y=20;
#Override
void foo(Class X) throws Exception {
if(X==B.class) {
y++;
System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
}
class C extends B {
int y=30;
#Override
void foo(Class X) throws Exception {
if(X==C.class) {
y++;
System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
void DoIt() {
try {
System.out.printf("DoIt: foo():\n");
foo();
Show();
System.out.printf("DoIt: foo(B):\n");
foo(B.class);
Show();
System.out.printf("DoIt: foo(A):\n");
foo(A.class);
Show();
} catch(Exception e) {
//...
}
}
void Show() {
System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
}
}
objC.DoIt() result output:
DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31
DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31
DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31
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
If you think you are going to be needing the superclass, you could reference it in a variable for that class. For example:
public class Foo
{
public int getNumber()
{
return 0;
}
}
public class SuperFoo extends Foo
{
public static Foo superClass = new Foo();
public int getNumber()
{
return 1;
}
}
public class UltraFoo extends Foo
{
public static void main(String[] args)
{
System.out.println(new UltraFoo.getNumber());
System.out.println(new SuperFoo().getNumber());
System.out.println(new SuperFoo().superClass.getNumber());
}
public int getNumber()
{
return 2;
}
}
Should print out:
2
1
0
public class SubSubClass extends SubClass {
#Override
public void print() {
super.superPrint();
}
public static void main(String[] args) {
new SubSubClass().print();
}
}
class SuperClass {
public void print() {
System.out.println("Printed in the GrandDad");
}
}
class SubClass extends SuperClass {
public void superPrint() {
super.print();
}
}
Output: Printed in the GrandDad
The keyword super is just a way to invoke the method in the superclass.
In the Java tutorial:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
Don't believe that it's a reference of the super object!!! No, it's just a keyword to invoke methods in the superclass.
Here is an example:
class Animal {
public void doSth() {
System.out.println(this); // It's a Cat! Not an animal!
System.out.println("Animal do sth.");
}
}
class Cat extends Animal {
public void doSth() {
System.out.println(this);
System.out.println("Cat do sth.");
super.doSth();
}
}
When you call cat.doSth(), the method doSth() in class Animal will print this and it is a cat.

Cannot reference this before supertype constructer has been called + Consumer

I'm attempting to define a generic abstract class that handles the processing/retrying logic of the implementing class. I want all implementing classes to pass a "process" and "fail" function that is executed by the abstract class. The abstract class also holds retry attempt logic and some other generic boilerplate code that I would like to reuse.
Specifically, I have the following abstract class:
public abstract class EnvelopeDispatcher<T> {
protected Consumer<T> processFn;
protected Consumer<T> failFn;
private MetricsRegistry metricsRegistry;
public EnvelopeDispatcher(MetricsRegistry metricsRegistry, Consumer<T> processFn, Consumer<T> failFn) {
this.metricsRegistry = metricsRegistry;
this.processFn = processFn;
this.failFn = failFn;
}
protected void process(T envelope) {
//abstract processing logic calling processFn and failFn
}
}
And the following implementing class:
public class ActionEnvelopeDispatcher extends EnvelopeDispatcher<ActionEnvelope> implements Consumer<ActionEnvelope> {
public ActionEnvelopeDispatcher(MetricsRegistry metricsRegistry ) {
super(metricsRegistry, this::processEnvelope, this::failEnvelope)
}
#Override
public void accept(#NonNull ActionEnvelope envelopeToProcess) {
super.process(envelopeToProcess);
}
private void processEnvelope( ... ) {
//processing logic
}
private void failEnvelope( ... ) {
//failure case logic
}
}
When I attempt to call super while referencing this::processEnvelope and this::failEnvelope I get "Cannot reference this before supertype constructer has been called".
I understand why this is happening, but I'm not sure of the alternatives. Does anyone know how to get around this or a better implementation pattern?
What you could do is don't make the dispatcher abstract and create it using factory methods.
Something like this:
class EnvelopeDispatchers {
// factory method
public static EnvelopeDispatcher<ActionEnvelope> actionEnvelopeDispatcher(MetricsRegistry metricsRegistry) {
return new EnvelopeDispatcher(metricsRegistry,
EnvelopeDispatchers::processEnvelope,
EnvelopeDispatchers::failEnvelope);
}
private static void processEnvelope(ActionEnvelope env) {
//processing logic
}
private static void failEnvelope(ActionEnvelope env) {
//failure case logic
}
}

Scjp: Java inheritance concept [duplicate]

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:
#Override
public String toString() {
return super.super.toString();
}
I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.
What do you guys think?
EDIT:
To clarify: yes I know, that's impossible in Java and I don't really miss it. This is nothing I expected to work and was surprised getting a compiler error. I just had the idea and like to discuss it.
It violates encapsulation. You shouldn't be able to bypass the parent class's behaviour. It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's. For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items". It makes sense to have:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
#Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
#Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
That's fine - RedItems can always be confident that the items it contains are all red. Now suppose we were able to call super.super.add():
public class NaughtyItems extends RedItems
{
#Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
Now we could add whatever we like, and the invariant in RedItems is broken.
Does that make sense?
I think Jon Skeet has the correct answer. I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
which produces the output:
x= 3
super.x= 2
((T2)this).x= 2
((T1)this).x= 1
((I)this).x= 0
(example from the JLS)
However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.
I think the following code allow to use super.super...super.method() in most case.
(even if it's uggly to do that)
In short
create temporary instance of ancestor type
copy values of fields from original object to temporary one
invoke target method on temporary object
copy modified values back to original object
Usage :
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}
I don't have enough reputation to comment so I will add this to the other answers.
Jon Skeet answers excellently, with a beautiful example. Matt B has a point: not all superclasses have supers. Your code would break if you called a super of a super that had no super.
Object oriented programming (which Java is) is all about objects, not functions. If you want task oriented programming, choose C++ or something else. If your object doesn't fit in it's super class, then you need to add it to the "grandparent class", create a new class, or find another super it does fit into.
Personally, I have found this limitation to be one of Java's greatest strengths. Code is somewhat rigid compared to other languages I've used, but I always know what to expect. This helps with the "simple and familiar" goal of Java. In my mind, calling super.super is not simple or familiar. Perhaps the developers felt the same?
There's some good reasons to do this. You might have a subclass which has a method which is implemented incorrectly, but the parent method is implemented correctly. Because it belongs to a third party library, you might be unable/unwilling to change the source. In this case, you want to create a subclass but override one method to call the super.super method.
As shown by some other posters, it is possible to do this through reflection, but it should be possible to do something like
(SuperSuperClass this).theMethod();
I'm dealing with this problem right now - the quick fix is to copy and paste the superclass method into the subsubclass method :)
In addition to the very good points that others have made, I think there's another reason: what if the superclass does not have a superclass?
Since every class naturally extends (at least) Object, super.whatever() will always refer to a method in the superclass. But what if your class only extends Object - what would super.super refer to then? How should that behavior be handled - a compiler error, a NullPointer, etc?
I think the primary reason why this is not allowed is that it violates encapsulation, but this might be a small reason too.
I think if you overwrite a method and want to all the super-class version of it (like, say for equals), then you virtually always want to call the direct superclass version first, which one will call its superclass version in turn if it wants.
I think it only makes rarely sense (if at all. i can't think of a case where it does) to call some arbitrary superclass' version of a method. I don't know if that is possible at all in Java. It can be done in C++:
this->ReallyTheBase::foo();
At a guess, because it's not used that often. The only reason I could see using it is if your direct parent has overridden some functionality and you're trying to restore it back to the original.
Which seems to me to be against OO principles, since the class's direct parent should be more closely related to your class than the grandparent is.
Calling of super.super.method() make sense when you can't change code of base class. This often happens when you are extending an existing library.
Ask yourself first, why are you extending that class? If answer is "because I can't change it" then you can create exact package and class in your application, and rewrite naughty method or create delegate:
package com.company.application;
public class OneYouWantExtend extends OneThatContainsDesiredMethod {
// one way is to rewrite method() to call super.method() only or
// to doStuff() and then call super.method()
public void method() {
if (isDoStuff()) {
// do stuff
}
super.method();
}
protected abstract boolean isDoStuff();
// second way is to define methodDelegate() that will call hidden super.method()
public void methodDelegate() {
super.method();
}
...
}
public class OneThatContainsDesiredMethod {
public void method() {...}
...
}
For instance, you can create org.springframework.test.context.junit4.SpringJUnit4ClassRunner class in your application so this class should be loaded before the real one from jar. Then rewrite methods or constructors.
Attention: This is absolute hack, and it is highly NOT recommended to use but it's WORKING! Using of this approach is dangerous because of possible issues with class loaders. Also this may cause issues each time you will update library that contains overwritten class.
#Jon Skeet Nice explanation.
IMO if some one wants to call super.super method then one must be want to ignore the behavior of immediate parent, but want to access the grand parent behavior.
This can be achieved through instance Of. As below code
public class A {
protected void printClass() {
System.out.println("In A Class");
}
}
public class B extends A {
#Override
protected void printClass() {
if (!(this instanceof C)) {
System.out.println("In B Class");
}
super.printClass();
}
}
public class C extends B {
#Override
protected void printClass() {
System.out.println("In C Class");
super.printClass();
}
}
Here is driver class,
public class Driver {
public static void main(String[] args) {
C c = new C();
c.printClass();
}
}
Output of this will be
In C Class
In A Class
Class B printClass behavior will be ignored in this case.
I am not sure about is this a ideal or good practice to achieve super.super, but still it is working.
Look at this Github project, especially the objectHandle variable. This project shows how to actually and accurately call the grandparent method on a grandchild.
Just in case the link gets broken, here is the code:
import lombok.val;
import org.junit.Assert;
import org.junit.Test;
import java.lang.invoke.*;
/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
return (MethodHandles.Lookup) field.get(null);
}
#Test
public void test() throws Throwable {
val lookup = getImplLookup();
val baseHandle = lookup.findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Sub.class);
val objectHandle = lookup.findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
// Must use Base.class here for this reference to call Object's toString
Base.class);
val sub = new Sub();
Assert.assertEquals("Sub", sub.toString());
Assert.assertEquals("Base", baseHandle.invoke(sub));
Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
}
private static String toString(Object o) {
return o.getClass().getName() + "#" + Integer.toHexString(o.hashCode());
}
public class Sub extends Base {
#Override
public String toString() {
return "Sub";
}
}
public class Base {
#Override
public String toString() {
return "Base";
}
}
}
Happy Coding!!!!
I would put the super.super method body in another method, if possible
class SuperSuperClass {
public String toString() {
return DescribeMe();
}
protected String DescribeMe() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return "I am super";
}
}
class ChildClass extends SuperClass {
public String toString() {
return DescribeMe();
}
}
Or if you cannot change the super-super class, you can try this:
class SuperSuperClass {
public String toString() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return DescribeMe(super.toString());
}
protected String DescribeMe(string fromSuper) {
return "I am super";
}
}
class ChildClass extends SuperClass {
protected String DescribeMe(string fromSuper) {
return fromSuper;
}
}
In both cases, the
new ChildClass().toString();
results to "I am super super"
It would seem to be possible to at least get the class of the superclass's superclass, though not necessarily the instance of it, using reflection; if this might be useful, please consider the Javadoc at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()
public class A {
#Override
public String toString() {
return "A";
}
}
public class B extends A {
#Override
public String toString() {
return "B";
}
}
public class C extends B {
#Override
public String toString() {
return "C";
}
}
public class D extends C {
#Override
public String toString() {
String result = "";
try {
result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
} catch (InstantiationException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}
public class Main {
public static void main(String... args) {
D d = new D();
System.out.println(d);
}
}
run:
A
BUILD SUCCESSFUL (total time: 0 seconds)
I have had situations like these when the architecture is to build common functionality in a common CustomBaseClass which implements on behalf of several derived classes.
However, we need to circumvent common logic for specific method for a specific derived class. In such cases, we must use a super.super.methodX implementation.
We achieve this by introducing a boolean member in the CustomBaseClass, which can be used to selectively defer custom implementation and yield to default framework implementation where desirable.
...
FrameworkBaseClass (....) extends...
{
methodA(...){...}
methodB(...){...}
...
methodX(...)
...
methodN(...){...}
}
/* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
CustomBaseClass(...) extends FrameworkBaseClass
{
private boolean skipMethodX=false;
/* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/
methodA(...){...}
methodB(...){...}
...
methodN(...){...}
methodX(...){
if (isSkipMethodX()) {
setSKipMethodX(false);
super.methodX(...);
return;
}
... //common method logic
}
}
DerivedClass1(...) extends CustomBaseClass
DerivedClass2(...) extends CustomBaseClass
...
DerivedClassN(...) extends CustomBaseClass...
DerivedClassX(...) extends CustomBaseClass...
{
methodX(...){
super.setSKipMethodX(true);
super.methodX(...);
}
}
However, with good architecture principles followed in framework as well as app, we could avoid such situations easily, by using hasA approach, instead of isA approach. But at all times it is not very practical to expect well designed architecture in place, and hence the need to get away from solid design principles and introduce hacks like this.
Just my 2 cents...
IMO, it's a clean way to achieve super.super.sayYourName() behavior in Java.
public class GrandMa {
public void sayYourName(){
System.out.println("Grandma Fedora");
}
}
public class Mama extends GrandMa {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName();
}else {
System.out.println("Mama Stephanida");
}
}
}
public class Daughter extends Mama {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName(lie);
}else {
System.out.println("Little girl Masha");
}
}
}
public class TestDaughter {
public static void main(String[] args){
Daughter d = new Daughter();
System.out.print("Request to lie: d.sayYourName(true) returns ");
d.sayYourName(true);
System.out.print("Request not to lie: d.sayYourName(false) returns ");
d.sayYourName(false);
}
}
Output:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
I think this is a problem that breaks the inheritance agreement.
By extending a class you obey / agree its behavior, features
Whilst when calling super.super.method(), you want to break your own obedience agreement.
You just cannot cherry pick from the super class.
However, there may happen situations when you feel the need to call super.super.method() - usually a bad design sign, in your code or in the code you inherit !
If the super and super super classes cannot be refactored (some legacy code), then opt for composition over inheritance.
Encapsulation breaking is when you #Override some methods by breaking the encapsulated code.
The methods designed not to be overridden are marked
final.
In C# you can call a method of any ancestor like this:
public class A
internal virtual void foo()
...
public class B : A
public new void foo()
...
public class C : B
public new void foo() {
(this as A).foo();
}
Also you can do this in Delphi:
type
A=class
procedure foo;
...
B=class(A)
procedure foo; override;
...
C=class(B)
procedure foo; override;
...
A(objC).foo();
But in Java you can do such focus only by some gear. One possible way is:
class A {
int y=10;
void foo(Class X) throws Exception {
if(X!=A.class)
throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
y++;
System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
}
void foo() throws Exception {
System.out.printf("A.foo()\n");
this.foo(this.getClass());
}
}
class B extends A {
int y=20;
#Override
void foo(Class X) throws Exception {
if(X==B.class) {
y++;
System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
}
class C extends B {
int y=30;
#Override
void foo(Class X) throws Exception {
if(X==C.class) {
y++;
System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
void DoIt() {
try {
System.out.printf("DoIt: foo():\n");
foo();
Show();
System.out.printf("DoIt: foo(B):\n");
foo(B.class);
Show();
System.out.printf("DoIt: foo(A):\n");
foo(A.class);
Show();
} catch(Exception e) {
//...
}
}
void Show() {
System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
}
}
objC.DoIt() result output:
DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31
DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31
DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31
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
If you think you are going to be needing the superclass, you could reference it in a variable for that class. For example:
public class Foo
{
public int getNumber()
{
return 0;
}
}
public class SuperFoo extends Foo
{
public static Foo superClass = new Foo();
public int getNumber()
{
return 1;
}
}
public class UltraFoo extends Foo
{
public static void main(String[] args)
{
System.out.println(new UltraFoo.getNumber());
System.out.println(new SuperFoo().getNumber());
System.out.println(new SuperFoo().superClass.getNumber());
}
public int getNumber()
{
return 2;
}
}
Should print out:
2
1
0
public class SubSubClass extends SubClass {
#Override
public void print() {
super.superPrint();
}
public static void main(String[] args) {
new SubSubClass().print();
}
}
class SuperClass {
public void print() {
System.out.println("Printed in the GrandDad");
}
}
class SubClass extends SuperClass {
public void superPrint() {
super.print();
}
}
Output: Printed in the GrandDad
The keyword super is just a way to invoke the method in the superclass.
In the Java tutorial:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
Don't believe that it's a reference of the super object!!! No, it's just a keyword to invoke methods in the superclass.
Here is an example:
class Animal {
public void doSth() {
System.out.println(this); // It's a Cat! Not an animal!
System.out.println("Animal do sth.");
}
}
class Cat extends Animal {
public void doSth() {
System.out.println(this);
System.out.println("Cat do sth.");
super.doSth();
}
}
When you call cat.doSth(), the method doSth() in class Animal will print this and it is a cat.

How To invoke a Method (with java reflection) from abstract class with generic type

The Classes simplified:
public abstract class AbstractFieldGroupBind<T> {
public Class<T> beanClass;
public BeanFieldGroup<T> binder;
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<T>(beanClass);
binder.bindMemberFields(vaadinComponent);
}
public class StammdataEditFGB extends AbstractFieldGroupBind<Cinema> {
public void pushItem(Item item) {
binder.setItemDataSource(item);
}
}
Now I try to invoke the method "initGroupBinder" by a composer Class.
If invoke the method like:
Method method = theFGBClass.getClass().getSuperclass().getDeclaredMethod("initGroupBinder", Object.class);
method.invoke(....)
If will call the class but without the Type . It will not work like this.
I also can get the generic superclass and there I find the type set in extends.
But how to bring it together to invoke the method like:
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<Cinema>(Cinema.class);
binder.bindMemberFields(vaadinComponent);
}
ADD: I get the class "StammdataEditFGB" in the composer via Spring by context.getBean(). This construct run in a Spring Context. So also a solution with Spring's ReflectionUtils is very welcome.
Found the solution! There 2 Problems.
1. getDeclaratedMedothod will not find methods there are in extented Classes. By using getMethod you will get methods (methods must be public) in Abstract Classes.
Here a small example to show.
public class Test {
public abstract class AbstractPerson{
public void callMe(){
System.out.println("Method callMe() in AbstractPerson");
}
}
public class Person extends AbstractPerson{}
public static void main(String[] args) {
Test test = new Test();
Person person = test.new Person();
try {
Method method;
System.out.println("### Use getMethod");
method = person.getClass().getMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
System.out.println("### Use getDeclaredMethod");
method = person.getClass().getDeclaredMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Console:
### Use getMethod
Method callMe() in AbstractPerson
### Use getDeclaredMethod
java.lang.NoSuchMethodException: Test$Person.callMe()
at java.lang.Class.getDeclaredMethod(Class.java:2004)
at Test.main(Test.java:27)
After solving that issue there has been the next one with generic type T.
2. The BeanFieldGroup could not be initialized like I did. Of course the beanClass is Null.
Here the solution with setting the beanClass for BeanFieldGroup properly:
public abstract class AbstractFieldGroupBind<T> implements IFieldGroupBind<T>{
protected BeanFieldGroup<T> binder;
#Override
public void initGroupBinder(Object view){
binder = new BeanFieldGroup<T>(getClassForT());
binder.bindMemberFields(view);
}
#Override
public void pushItem(T item) {
binder.setItemDataSource(item);
}
#Override
public T getItem() {
return binder.getItemDataSource().getBean();
}
#SuppressWarnings("unchecked")
private Class<T> getClassForT(){
Type superClazz = this.getClass().getGenericSuperclass();
Type tClazz = ((ParameterizedType)superClazz).getActualTypeArguments()[0];
return (Class<T>) tClazz;
}
}
Now it works!
When you instantiate an object of class StammdataEditFGB, you are already passing the type information to the super class. So, when you call theFGBClass.getClass().getSuperClass(), you will get a AbstractFieldGroupBind class that handles Cinema objects.

Categories