Why is super.super.method(); not allowed in Java? - java

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.

Related

Call super.super.method, skipping super.method

I have the following (third-party) class structure. We'll call the third-party project ProjectSeriously, and note that I'm using System.out.println in place of other complicated functionality (100s of lines of code).
class A {
public void hi() {
// Do an important thing
System.out.println("Important thing A");
}
}
class B extends A {
public void hi() {
// Do some terrible, terrible things
System.out.println("TERRIBLE THING B");
// Do that important thing
super.hi();
}
}
Now I want to write this (this isn't valid java):
class C extends B {
public void hi() {
// Do some not-so-terrible things
System.out.println("Ok thing C");
// Do that important thing
super.super.hi();
}
}
I have to pass an instanceof B to some other piece of this wonderful project, ProjectSeriously. Seeing as these are public methods, I feel like this should be possible.
You could use javassist to modify the class before any use of it.
But this is a really ugly hack, please try to refactor the code in A and/or B the expose the important parts.
package test;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
class A {
public void hi() {
// Do an important thing
System.out.println("Important thing A");
}
}
class B extends A {
public void hi() {
// Do some terrible, terrible things
System.out.println("TERRIBLE THING B");
// Do that important thing
super.hi();
}
}
class C extends B {
public void hi() {
// Do some not-so-terrible things
System.out.println("Ok thing C");
// Do that important thing
super.hi();
}
}
public class Main {
public static void main(String[] args) throws Exception {
CtClass cc = ClassPool.getDefault().get("test.B"); // don't use test.B.class.getName() as this force the class loader to load the class
CtMethod m1 = cc.getDeclaredMethod("hi");
cc.removeMethod(m1);
CtMethod m2 = CtNewMethod.copy(m1, cc, null);
m2.setBody("{ /* override method B.hi() body */ return super.hi();}", "this", m1.getName());
cc.addMethod(m2);
cc.toClass();
C obj = new C();
obj.hi();
}
}
Result:
Ok thing C
Important thing A
Unless you explicitly expose the method(s), which sort-of goes against the design pattern, there aren't many other options:
public class GrandParent {
public void hi() {
hiGrandParent();
}
protected final void hiGrandParent() {
System.out.println("Hi from grandparent.");
}
public static class Parent extends GrandParent {
#Override
public void hi() {
hiParent();
}
protected final void hiParent() {
System.out.println("Hi from parent.");
}
}
public static class Child extends Parent {
#Override
public void hi() {
hiChild();
super.hi();
hiParent();
hiGrandParent();
}
protected final void hiChild() {
System.out.println("Hi from child.");
}
}
}
Run with:
public final class RunIt {
public static void main(final String[] args) {
new GrandParent.Child().hi();
}
}
Expected output:
Hi from child.
Hi from parent.
Hi from parent.
Hi from grandparent.
This would break encapsulation in a terrible way (you'd essentially be disabling some part of class B's logic), and it shouldn't be possible in Java. I'm pretty sure it isn't possible.
Yeah its not really possible in a "standard" java way, also its a bad design decision but OP might not have access to the original class. I've faced this problem several times earlier with different jars.
If you want to skip for example a private method call in one of the super classes, but still need the other parts of the constructor code or the functionality of the superclasses, the only "easy" way to do this is to basically copy-paste that part of the code into your own class. For example if you have these classes:
public class Foo {
public Foo() {
importantFunctionality();
}
private void importantFunctionality() {
System.out.println("DOING IMPORTANT STUFF");
}
}
public class Bar extends Foo {
public Bar() {
super(); //constructor gets called
killAllBabies(); //I dont want this to get called, but its a private method meaning no overriding
solveWorldHunger(); //I want to call this, but this is a private method, so no calling this from child classes
}
private void killAllBabies() {
System.out.println("KILLING ALL BABIES");
}
private void solveWorldHunger() {
System.out.println("SOLVING WORLD HUNGER");
}
}
public class MyClass extends Bar {
public MyClass() {
super(); //Not good, because stuff I dont want gets called here
}
}
Only way to solve this is to "skip" the previous class and extend the original class and implement the functionality of the skipped class. Unfortunately this was an issue for us with a certain framework because of bad extendibility:
public class MyClass extends Foo {
public MyClass() {
super();
solveWorldHunger();
}
private void solveWorldHunger() {
System.out.println("SOLVING WORLD HUNGER");
}
}

Java: method only callable by superclass

I would like to prevent a class from calling its own method. The method shall only be callable by its super class.
Right now, I cannot think of any way to achieve this (cleanly). But maybe someone knows a solution?
In code:
public abstract class A {
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
public class B extends A {
#Override
protected void foo() {
//do smth
}
private void barB() {
//must not be able to call foo() here
}
}
Edit: the explanation why I would like to do this:
A is lets say a vehicle. B can be a car or an airplane. The method foo() would be startEngines(). -> I want to make sure that the engines can only be started by calling the method barA().... does that make any sense?
There is a way to do it, but you need to use Google Error Prone. This is an extension of the Java compiler that aims to provide more and more helpful warnings and errors (similar to FindBugs and PMD, but with less false alarms). I can only recommend it, it has already helped us to find some bugs.
Specifically, it contains an annotation #ForOverride and an according compile-time check. This annotation is meant to be used for protected methods that the sub-class and any other class should not call, but only the defining class.
So using
public abstract class A {
#ForOverride
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
would exactly achieve what you want.
You can integrate Error Prone into most build systems like Maven and Ant. Of course, it won't help if somebody compiles your source without Error Prone (for example in Eclipse), but using it in a continous-integration system would still allow you to find such issues. The source code still stays compatible with regular Java compilers (provided you have error_prone_annotations.jar on the class path), other compilers will simply not do the additional checks.
this answer has a good hint.
add below method in your class (class B):
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
return ste[ste.length - 1 - depth].getMethodName();
}
and change the foo method in class B to this:
#Override
protected void foo() {
//....
if (getMethodName(0)=="barB"){
// tell you are not able to call barB
}
}
Considering your vehicle and engine scenario, I think you need to reconsider your design a bit.
Your vehicle could be a car, aeroplane, etc but car, aeroplane, ... each have separate engines and therefore different startEngine method. So declare your class vehicle as abstract like you did and class startEngine as abstract method . Next , subclass Vehicle and implement startEngine in them , now you can invoke startEngine on the subclass instances
abstract class Vehicle{
abstract void startEngine();
}
public class Car extends Vehicle{
public void startEngine(){
//implementation
}
public static void main(String[] arg){
Vehicle v=new Car();
v.startEngine();
}
}
Add Anonymouse inner class to barA method via Interface, so you will need to implement a method for foo() (functional interface). It won't be part of Class B.
you could put an interface as a member in the super class given to it via the constructor. the child class implements the method but can't call it except by making it static.
interface Foo {
void stopEngines();
void startEngines();
}
abstract class Base {
final private Foo foo;
public Base(final Foo foo) {
this.foo = foo;
}
private void barA() {
// do smth
foo.startEngines();
}
}
class Child extends Base {
public Child() {
super(new Foo() {
boolean engineRunning;
#Override
public void stopEngines() {
this.engineRunning = false;
}
#Override
public void startEngines() {
this.engineRunning = true;
}
});
}
private void barB() {
// can't call startEngines() or stopEngines() here
}
}
class Child2 extends Base {
public Child2() {
super(new Foo() {
#Override
public void stopEngines() {
stopEngines();
}
#Override
public void startEngines() {
startEngines();
}
});
}
static void stopEngines() {
// influence some static state?
}
static void startEngines() {
// influence some static state?
}
private void barB() {
// can call stopEngines() and startEngines(), but at least they have to be static
}
}
Of course, this is not really what you asked for, but about as much as you can do about it in Java, I guess.
Seeing the startEngines explanation, this solution might even suffice.
I guess you wouldn't care about the class calling its static methods, since they can only influence a static state, which is used seldom. The methods within the anonymous interface implementation can mutually call each other, but I guess that would be OK, since you only seem to be trying to prevent others to start the engines in some different way.
I guess this is similar to the problem AWT/Swing has with overriding the paint(Graphics g) method on a component (or onCreate(..) in Android Activities). Here you are overriding the paint method but you should never call it.
I think the best thing you can do is add documentation to the method to clarify that it should never be explicitly called by the subclasses OR re-evaluate your design.

Java multi-type method parameter?

I wonder if it is possible to require that a java method parameter is of any type from finite set of types. For example - I am using a library where two (or more) types have common methods, but their lowest common ancestor in the type hierarchy is Object. What I mean here:
public interface A {
void myMethod();
}
public interface B {
void myMethod();
}
...
public void useMyMethod(A a) {
// code duplication
}
public void useMyMethod(B b) {
// code duplication
}
I want to avoid the code duplication. What I think of is something like this:
public void useMyMethod(A|B obj){
obj.myMethod();
}
There is similar type of syntax in java already. For example:
try{
//fail
} catch (IllegalArgumentException | IllegalStateException e){
// use e safely here
}
Obviously this is not possible. How can I achieve well designed code using such type of uneditable type hierarchy ?
What about passing the function as a parameter to your useMyMethod function?
If you are using Java < 8:
public interface A {
void myMethod();
}
public interface B {
void myMethod();
}
public void useMyMethod(Callable<Void> myMethod) {
try {
myMethod.call();
} catch(Exception e) {
// handle exception of callable interface
}
}
//Use
public void test() {
interfaceA a = new ClassImplementingA();
useMyMethod(new Callable<Void>() {
public call() {
a.myMethod();
return null;
}
});
interfaceB b = new ClassImplementingB();
useMyMethod(new Callable<Void>() {
public call() {
b.myMethod();
return null;
}
});
}
For Java >= 8, you could use Lambda Expressions:
public interface IMyMethod {
void myMethod();
}
public void useMyMethod(IMyMethod theMethod) {
theMethod.myMethod();
}
//Use
public void test() {
interfaceA a = new ClassImplementingA();
useMyMethod(() -> a.myMethod());
interfaceB b = new ClassImplementingB();
useMyMethod(() -> b.myMethod());
}
Try using Adapter design pattern.
Or, if it's possible, add some base interface:
public interface Base {
void myMethod();
}
public interface A extends Base {}
public interface B extends Base {}
...
public void useMyMethod(Base b) {
b.myMethod()
}
Also, you can use something similar to this
You could write an interface MyInterface with a single method myMethod. Then, for each type you want to consider as part of the finite set, write a wrapper class, like this:
class Wrapper1 implements MyInterface {
private final Type1 type1;
Wrapper1(Type1 type1) {
this.type1 = type1;
}
#Override
public void myMethod() {
type1.method1();
}
}
Then you just need to use a MyInterface rather than one of the finite set of types, and the appropriate method from the appropriate type will always get called.
Note that to actually use these wrapper classes to call the method myMethod you would have to write
myMethod(new Wrapper1(type1));
This is going to get a bit ugly as you are going to have to remember the name of the wrapper class for each type in the set. For this reason, you may prefer to replace MyInterfacewith an abstract class with several static factories that produce the wrapper types. Like this:
abstract class MyWrapper {
static MyWrapper of(Type1 type1) {
return new Wrapper1(type1);
}
static MyWrapper of(Type2 type2) {
return new Wrapper2(type2);
}
abstract void myMethod();
}
then you can call the method using the code
myMethod(MyWrapper.of(type1));
The advantage of this approach is that the code is the same no matter which type you use. If you use this approach you have to replace implements MyInterface in the Wrapper1 declaration with extends MyWrapper.
Well, the correct way to model your requirement would be to have myMethod() declared in a supertype interface C which both A and B extend; your method then accepts type C as its parameter. The fact that you have trouble doing this in the situation you describe indicates you are not modelling the class hierarchy in a way that actually reflects how they behave.
Of course, if you can't change the interface structure then you could always do it with reflections.
public static void useMyMethod(Object classAorB) throws Exception {
classAorB.getClass().getMethod("myMethod").invoke(classAorB);
}
This might not constitute a best practice, but could you make a new class (call it C), that contains the parts from A and B that are duplicated, and the make a new method that takes C, have your methods that take A and B make a C instance and call the new method?
So that you have
class C {
// Stuff from both A and B
}
public void useMyMethod(A a) {
// Make a C
useMyMethod(c);
}
public void useMyMethod(B b) {
// Make a C
useMyMethod(c);
}
public void useMyMethod(C c) {
// previously duplicated code
}
That would also let you keep any non duplicated code in the methods for A and B (if there is any).
This looks to me much like the template pattern:
public interface A {
void myMethod();
}
public interface B {
void myMethod();
}
public class C {
private abstract class AorBCaller {
abstract void myMethod();
}
public void useMyMethod(A a) {
commonAndUseMyMethod(new AorBCaller() {
#Override
void myMethod() {
a.myMethod();
}
});
}
public void useMyMethod(B b) {
commonAndUseMyMethod(new AorBCaller() {
#Override
void myMethod() {
b.myMethod();
}
});
}
private void commonAndUseMyMethod(AorBCaller aOrB) {
// ... Loads of stuff.
aOrB.myMethod();
// ... Loads more stuff
}
}
In Java 8 it is much more succinct:
public class C {
// Expose an "A" form of the method.
public void useMyMethod(A a) {
commonAndUseMyMethod(() -> a.myMethod());
}
// And a "B" form.
public void useMyMethod(B b) {
commonAndUseMyMethod(() -> b.myMethod());
}
private void commonAndUseMyMethod(Runnable aOrB) {
// ... Loads of stuff -- no longer duplicated.
aOrB.run();
// ... Loads more stuff
}
}
A dynamic proxy can be used to create a bridge between a common interface you define and the objects implementing the other interfaces that conform to the new interface. Then, you can have your useMyMethods convert the parameter to the new interface (as a dynamic proxy) and have your common code written in terms only of the new interface.
This would be the new interface:
interface Common {
void myMethod();
}
Then, with this invocation handler:
class ForwardInvocationHandler implements InvocationHandler {
private final Object wrapped;
public ForwardInvocationHandler(Object wrapped) {
this.wrapped = wrapped;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method match = wrapped.getClass().getMethod(method.getName(), method.getParameterTypes());
return match.invoke(wrapped, args);
}
}
You can have your methods like this:
public void useMyMethod(A a) {
useMyMethod(toCommon(a));
}
public void useMyMethod(B b) {
useMyMethod(toCommon(b));
}
public void useMyMethod(Common common) {
// ...
}
private Common toCommon(Object o) {
return (Common)Proxy.newProxyInstance(
Common.class.getClassLoader(),
new Class[] { Common.class },
new ForwardInvocationHandler(o));
}
Note that to simplify matters you could even elect one of your existing interfaces (A or B) to be used as the common interface.
(Look at another example here, and also at other ideas around this subject)
The correct way is to use Java Generics.
See http://docs.oracle.com/javase/tutorial/java/generics/bounded.html

Implementing two interfaces with two default methods of the same signature in Java 8

Suppose I have two interfaces:
public interface I1
{
default String getGreeting() {
return "Good Morning!";
}
}
public interface I2
{
default String getGreeting() {
return "Good Afternoon!";
}
}
If I want to implement both of them, what implementation will be used?
public class C1 implements I1, I2
{
public static void main(String[] args)
{
System.out.println(new C1().getGreeting());
}
}
This is a compile-time error. You cannot have two implementation from two interfaces.
However, it is correct, if you implement the getGreeting method in C1:
public class C1 implements I1, I2 // this will compile, bacause we have overridden getGreeting()
{
public static void main(String[] args)
{
System.out.println(new C1().getGreeting());
}
#Override public String getGreeting()
{
return "Good Evening!";
}
}
I just want to add that even if the method in I1 is abstract, and default in I2, you cannot implement both of them. So this is also a compile-time error:
public interface I1
{
String getGreeting();
}
public interface I2
{
default String getGreeting() {
return "Good afternoon!";
}
}
public class C1 implements I1, I2 // won't compile
{
public static void main(String[] args)
{
System.out.println(new C1().getGreeting());
}
}
This is not specific to the question. But, I still think that it adds some value to the context. As an addition to #toni77's answer, I would like to add that the default method can be invoked from an implementing class as shown below. In the below code, the default method getGreeting() from interface I1 is invoked from an overridden method:
public interface I1 {
default String getGreeting() {
return "Good Morning!";
}
}
public interface I2 {
default String getGreeting() {
return "Good Night!";
}
}
public class C1 implements I1, I2 {
#Override
public String getGreeting() {
return I1.super.getGreeting();
}
}
If a class implements 2 interfaces both of which have a java-8 default method with the same signature (as in your example) the implementing class is obliged to override the method. The class can still access the default method using I1.super.getGreeting();. It can access either, both or neither. So the following would be a valid implementation of C1
public class C1 implements I1, I2{
public static void main(String[] args)
{
System.out.println(new C1().getGreeting());
}
#Override //class is obliged to override this method
public String getGreeting() {
//can use both default methods
return I1.super.getGreeting()+I2.super.getGreeting();
}
public String useOne() {
//can use the default method within annother method
return "One "+I1.super.getGreeting();
}
public String useTheOther() {
//can use the default method within annother method
return "Two "+I2.super.getGreeting();
}
}
There is a case where this actually works according to the resolution rules. If one of the interfaces extends one of the others.
Using the example from above:
public interface I2 extends I1 {
default String getGreeting() {
return "Good Afternoon!";
}
}
The result would be:
Good Afternoon!
However, I believe this is going to be a big problem. The whole reason for default interfaces is to allow library developers to evolve apis without breaking implementers.
Understandably they don't allow the methods to compile without the inheritance structure via extension because a library developer could potentially hijack behavior.
However, this has the potential to be self defeating. If a class implements two interfaces that are not related from a hierarchical view, but both define the same default method signature, then the class that extends both interfaces will not compile. (as demonstrated above)
It is conceivable that two different library developers could decide to add default methods at different times using common signatures; in fact it is probable that this will happen in libraries that implement similar concepts such as math libraries. If you happen to be the sorry soul implementing both interfaces in the same class you will be broken on update.
I believe the rule is that the class implementing the duplicate default methods 'must' override the implementation.. The following compiles and runs fine...
public class DupeDefaultInterfaceMethods {
interface FirstAbility {
public default boolean doSomething() {
return true;
}
}
interface SecondAbility {
public default boolean doSomething() {
return true;
}
}
class Dupe implements FirstAbility, SecondAbility {
#Override
public boolean doSomething() {
return false;
}
}
public static void main(String[] args) {
DupeDefaultInterfaceMethods ddif = new DupeDefaultInterfaceMethods();
Dupe dupe = ddif.new Dupe();
System.out.println(dupe.doSomething());
}
}
> false
This is the simple way:
public interface Circle{
default String shape() {
return "Circle drawn...";
}
}
public interface Rectangle{
default String shape() {
return "Rectangle drawn...";
}
}
public class Main implements Circle, Rectangle{
#Override
public String shape() {
return Circle.super.shape();// called using InterfaceName.super.methodName
}
}
Output:
Circle drawn...
Default methods in Java 8 can be viewed as a form of multiple inheritance (except that attribute can not be inherited).
The main motivation behind default methods is that if at some point we need to add a method to an existing interface, we can add a method without changing the existing implementation classes. In this way, the interface is still compatible with older versions. This is a cool feature. However, we should remember the motivation of using Default Methods and should keep the separation of interface and implementation.
interface First{
// default method
default void show(){
System.out.println("Default method implementation of First interface.");
} }
interface Second{
// Default method
default void show(){
System.out.println("Default method implementation of Second interface.");
} }
// Implementation class code
public class Example implements First, Second{
// Overriding default show method
public void show(){
First.super.show();
Second.super.show();
}
public static void main(String args[]){
Example e = new Example();
e.show();
} }

Java abstract method with abstract parameter and inheritance

I recently fumbled into a problem with an API and an implementation where the following type of code appeared:
public abstract class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
}
The implementation is a simple class:
public class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
}
When it comes to using it I write:
public class Main {
public static void main(String[] args) {
B b = new B();
A basa = new B();
b.sum(b);
basa.sum(b);
basa.sum(basa);
}
}
Which results in:
B.sum(B) called
A.sum(A) called
A.sum(A) called
I understand that B's sum does not override A's sum as its signature is different, but I'd like to provide an efficient implementation of sum for objects of effective type B. I think such design is quite classical and I would like to know how I should design my API and implementation so that it is efficient.
Of course I could provide sum(A a) in class B and check if b is an instanceof B before calling either sum(B b) or super, but I thought that instanceof was to be avoided for efficiency reasons. (if it is inefficient, it may be even less efficient with my abstract implementation)
instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose. In the example below I removed abstract from A to illustrate how it works with different types.
The trick is that when an object is asked to visit a visitor, the object itself chooses the correct accept method in the visitor. The "instanceof"-check is resolved through polymorphism. (I doubt that it's more efficient than an instanceof though.)
interface Visitor {
public A accept(A a);
public B accept(B b);
}
class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
public A visit(Visitor sv) {
return sv.accept(this);
}
}
class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
public B visit(Visitor sv) {
return sv.accept(this);
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A basa = new B();
a.visit(new SumVisitor(b)); // a.sum(b);
b.visit(new SumVisitor(b)); // b.sum(b);
basa.visit(new SumVisitor(b)); // basa.sum(b);
basa.visit(new SumVisitor(basa)); // basa.sum(basa);
}
static class SumVisitor implements Visitor {
A arg;
SumVisitor(A arg) { this.arg = arg; }
public A accept(A a) { return a.sum(arg); }
public B accept(B b) { return b.sum(arg); }
}
}
Output:
A.sum(A) called
B.sum(B) called
B.sum(B) called
B.sum(B) called
Disclamer; It was a while ago I wrote a visitor, so please correct me if I have any bugs in this (almost untested) code snippet. Or better, edit the post yourself and improve it :)
Since B instances can be summed with A instances using myA.sum(myB), you should be able to change B's definition of sum so that it does override, unless of course sum is a placeholder and isn't something that should be commutative.
UPDATE:
If this is insufficient, you could start getting fancy with generics. Here's a rough pass at what I mean:
public abstract class A {
public <T extends A> T sum(T a) {
System.out.println("A.sum(A) called");
return null;
}
public static void main(String args[]) {
B b = new B();
b.sum(b);
A basa = new B();
basa.sum(b);
basa.sum(basa);
}
public static class B extends A {
#Override
public <T extends A> T sum(T b) {
System.out.println("B.sum(B) called");
return null;
}
}
}
#aioobe is right that the generally accepted work-around is to use the Visitor pattern. I'm offering these as less complete but less verbose alternatives.
So, what makes you think instanceof is slow? It's used in several places in the JDK where they want to provide a "fast path" for certain well-known implementations of an abstract class or interface. The usual advice applies here: "Test, don't guess."

Categories

Resources