I have a collection (or list or array list) in which I want to put both String values and double values. I decided to make it a collection of objects and using overloading ond polymorphism, but I did something wrong.
I run a little test:
public class OOP {
void prova(Object o){
System.out.println("object");
}
void prova(Integer i){
System.out.println("integer");
}
void prova(String s){
System.out.println("string");
}
void test(){
Object o = new String(" ");
this.prova(o); // Prints 'object'!!! Why?!?!?
}
public static void main(String[] args) {
OOP oop = new OOP();
oop.test(); // Prints 'object'!!! Why?!?!?
}
}
In the test seems like the argument type is decided at compile time and not at runtime. Why is that?
This question is related to:
Polymorphism vs Overriding vs Overloading
Try to describe polymorphism as easy as you can
EDIT:
Ok the method to be called is decided at compile time. Is there a workaround to avoid using the instanceof operator?
This post seconds voo's answer, and gives details about/alternatives to late binding.
General JVMs only use single dispatch: the runtime type is only considered for the receiver object; for the method's parameters, the static type is considered. An efficient implementation with optimizations is quite easy using method tables (which are similar to C++'s virtual tables). You can find details e.g. in the HotSpot Wiki.
If you want multiple dispatch for your parameters, take a look at
groovy. But to my latest knowledge, that has an outdated, slow multiple dispatch implementation (see e.g. this performance comparison), e.g. without caching.
clojure, but that is quite different to Java.
MultiJava, which offers multiple dispatch for Java. Additionally, you can use
this.resend(...) instead of super(...) to invoke the most-specific overridden method of the enclosing method;
value dispatching (code example below).
If you want to stick with Java, you can
redesign your application by moving overloaded methods over a finer grained class hierarchy. An example is given in Josh Bloch's Effective Java, Item 41 (Use overloading judiciously);
use some design patterns, such as Strategy, Visitor, Observer. These can often solve the same problems as multiple dispatch (i.e. in those situations you have trivial solutions for those patterns using multiple dispatch).
Value dispatching:
class C {
static final int INITIALIZED = 0;
static final int RUNNING = 1;
static final int STOPPED = 2;
void m(int i) {
// the default method
}
void m(int##INITIALIZED i) {
// handle the case when we're in the initialized `state'
}
void m(int##RUNNING i) {
// handle the case when we're in the running `state'
}
void m(int##STOPPED i) {
// handle the case when we're in the stopped `state'
}
}
What you want is double or more general multiple dispatch, something that is actually implemented in other languages (common lisp comes to mind)
Presumably the main reason java doesn't have it, is because it comes at a performance penalty because overload resolution has to be done at runtime and not compile time. The usual way around this is the visitor pattern - pretty ugly, but that's how it is.
Old question but no answer provides a concrete solution in Java to solve the issue in a clean way.
In fact, not easy but very interesting question. Here is my contribution.
Ok the method to be called is decided at compile time. Is there a
workaround to avoid using the instanceof operator?
As said in the excellent #DaveFar answer, Java supports only the single-dispatch method.
In this dispatching mode, the compiler bounds the method to invoke as soon as the compilation by relying on the declared types of the parameters and not their runtime types.
I have a collection (or list or array list) in which I want to put
both String values and double values.
To solve the answer in a clean way and use a double dispatch, we have to bring abstraction for the manipulated data.
Why ?
Here a naive visitor approach to illustrate the issue :
public class DisplayVisitor {
void visit(Object o) {
System.out.println("object"));
}
void visit(Integer i) {
System.out.println("integer");
}
void visit(String s) {
System.out.println("string"));
}
}
Now, question : how visited classes may invoke the visit() method ?
The second dispatch of the double dispatch implementation relies on the "this" context of the class that accepts to be visited.
So we need to have a accept() method in Integer, String and Object classes to perform this second dispatch :
public void accept(DisplayVisitor visitor){
visitor.visit(this);
}
But impossible ! Visited classes are built-in classes : String, Integer, Object.
So we have no way to add this method.
And anyway, we don't want to add that.
So to implement the double dispatch, we have to be able to modify the classes that we want to pass as parameter in the second dispatch.
So instead of manipulating Object and List<Object> as declared type, we will manipulate Foo and List<Foo> where the Foo class is a wrapper holding the user value.
Here is the Foo interface :
public interface Foo {
void accept(DisplayVisitor v);
Object getValue();
}
getValue() returns the user value.
It specifies Object as return type but Java supports covariance returns (since the 1.5 version), so we could define a more specific type for each subclass to avoid downcasts.
ObjectFoo
public class ObjectFoo implements Foo {
private Object value;
public ObjectFoo(Object value) {
this.value = value;
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
#Override
public Object getValue() {
return value;
}
}
StringFoo
public class StringFoo implements Foo {
private String value;
public StringFoo(String string) {
this.value = string;
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
#Override
public String getValue() {
return value;
}
}
IntegerFoo
public class IntegerFoo implements Foo {
private Integer value;
public IntegerFoo(Integer integer) {
this.value = integer;
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
#Override
public Integer getValue() {
return value;
}
}
Here is the DisplayVisitor class visiting Foo subclasses :
public class DisplayVisitor {
void visit(ObjectFoo f) {
System.out.println("object=" + f.getValue());
}
void visit(IntegerFoo f) {
System.out.println("integer=" + f.getValue());
}
void visit(StringFoo f) {
System.out.println("string=" + f.getValue());
}
}
And here is a sample code to test the implementation :
public class OOP {
void test() {
List<Foo> foos = Arrays.asList(new StringFoo("a String"),
new StringFoo("another String"),
new IntegerFoo(1),
new ObjectFoo(new AtomicInteger(100)));
DisplayVisitor visitor = new DisplayVisitor();
for (Foo foo : foos) {
foo.accept(visitor);
}
}
public static void main(String[] args) {
OOP oop = new OOP();
oop.test();
}
}
Output :
string=a String
string=another String
integer=1
object=100
Improving the implementation
The actual implementation requires the introduction of a specific wrapper class for each buit-in type we want to wrap.
As discussed, we don't have the choice to operate a double dispatch.
But note that the repeated code in Foo subclasses could be avoided :
private Integer value; // or String or Object
#Override
public Object getValue() {
return value;
}
We could indeed introduce a abstract generic class that holds the user value and provides an accessor to :
public abstract class Foo<T> {
private T value;
public Foo(T value) {
this.value = value;
}
public abstract void accept(DisplayVisitor v);
public T getValue() {
return value;
}
}
Now Foo sublasses are lighter to declare :
public class IntegerFoo extends Foo<Integer> {
public IntegerFoo(Integer integer) {
super(integer);
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
}
public class StringFoo extends Foo<String> {
public StringFoo(String string) {
super(string);
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
}
public class ObjectFoo extends Foo<Object> {
public ObjectFoo(Object value) {
super(value);
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
}
And the test() method should be modified to declare a wildcard type (?) for the Foo type in the List<Foo> declaration.
void test() {
List<Foo<?>> foos = Arrays.asList(new StringFoo("a String object"),
new StringFoo("anoter String object"),
new IntegerFoo(1),
new ObjectFoo(new AtomicInteger(100)));
DisplayVisitor visitor = new DisplayVisitor();
for (Foo<?> foo : foos) {
foo.accept(visitor);
}
}
In fact, if really needed, we could simplify further Foo subclasses by introducing java code generation.
Declaring this subclass :
public class StringFoo extends Foo<String> {
public StringFoo(String string) {
super(string);
}
#Override
public void accept(DisplayVisitor v) {
v.visit(this);
}
}
could as simple as declaring a class and adding an annotation on:
#Foo(String.class)
public class StringFoo { }
Where Foo is a custom annotation processed at compile time.
When calling a method that is overloaded, Java picks the most restrictive type based on the type of the variable passed to the function. It does not use the type of the actual instance.
this isn't polymoprhism, you've simply overloaded a method and called it with parameter of object type
Everything in Java is an Object/object (except primitive types). You store strings and integers as objects, and then as you call the prove method they are still referred to as objects. You should have a look at the instanceof keyword. Check this link
void prove(Object o){
if (o instanceof String)
System.out.println("String");
....
}
I am a beginner and i try to teach myself clean coding. I want to pass a function as a parameter that I can reuse a method without to repeat code. As an example I have this:
public class Dog {
private String name;
private int id;
private List<String> characteristic;
public List<String> getCharacteristic() {
return characteristic;
}
public void setCharacteristic(List<String> characteristic) {
this.characteristic = characteristic;
}
}
public class Check{
private List<Dog> dogs = new ArrayList();
public void iterate() {
while (dogs.size() > 0) {
for (Dog dog : dogs) {
List<String> restChara = new ArrayList<>();
restChara= checkChara(dog, restChara);
if (restChara.size()>0) {
dog.setCharacteristic(restChara);
} else {
dogs.remove(dog);
}
}
}
}
private List<String> checkChara(Dog dog, List<String> restChara) {
for (String chara : dog.getCharacteristic()) {
boolean charaChecked = doSomething(chara);
if (!charaChecked) {
restChara.add(chara);
} else {
dog.getCharacteristic().remove(chara);
}
}
return restChara;
}
private boolean doSomething(String chara){
//do sth.
return true;
}
private boolean doSomething2(String chara){
//do sth.
return true;
}
}
How would you define the method checkChara in order to use different functions within it?
My first thought was to pass the function as a parameter (i think it would be in C# delegates)
Thank you very much!
EDIT:
I think I found another pattern strategy design pattern
https://www.freecodecamp.org/news/the-strategy-pattern-explained-using-java-bc30542204e0/
Java does not support “directly” nested methods. Many functional programming languages support method within method. But you can achieve nested method functionality in Java 7 or older version by define local classes, class within method so this does compile. And in java 8 and newer version you achieve it by lambda expression.
Method 1 (Using anonymous subclasses)
It is an inner class without a name and for which only a single object is created. An anonymous inner class can be useful when making an instance of an object with certain “extras” such as overloading methods of a class or interface, without having to actually subclass a class.
//Java program implements method inside method
public class GFG {
// create a local interface with one abstract
// method run()
interface myInterface {
void run();
}
// function have implements another function run()
static void Foo()
{
// implement run method inside Foo() function
myInterface r = new myInterface() {
public void run()
{
System.out.println("geeksforgeeks");
};
};
r.run();
}
public static void main(String[] args)
{
Foo();
}
}
Method 2 (Using local classes)
You can also implement a method inside a local class. A class created inside a method is called local inner class. If you want to invoke the methods of local inner class, you must instantiate this class inside method.
// Java program implements method inside method
public class GFG {
// function have implementation of another
// function inside local class
static void Foo()
{
// local class
class Local {
void fun()
{
System.out.println("geeksforgeeks");
}
}
new Local().fun();
}
public static void main(String[] args)
{
Foo();
}
}
Method 3 (Using a lambda expression)
Lambda expressions basically express instances of functional interfaces (An interface with single abstract method is called functional interface. An example is java.lang.Runnable). lambda expressions implement the only abstract function and therefore implement functional interfaces.
// Java program implements method inside method
public class GFG {
interface myInterface {
void run();
}
// function have implements another function
// run() using Lambda expression
static void Foo()
{
// Lambda expression
myInterface r = () ->
{
System.out.println("geeksforgeeks");
};
r.run();
}
public static void main(String[] args)
{
Foo();
}
}
I don't exaclty know what you mean, but i figure out it could be something like that:
List<Runnable> runMyStuff = new ArrayList<Runnable>();
String variable= "Hallo"; //needs to be effectively final
runMyStuff.add(() -> {
System.out.println(variable);
doSomething(variable);
});
runMyStuff.add(() ->{
System.out.println("This is a test");
});
runMyStuff.add(() ->{
System.out.println("2 + 2 = " + (2+2) );
});
runMyStuff.get(0).run();
runMyStuff.get(2).run();
runMyStuff.get(0).run();
runMyStuff.get(1).run();
runMyStuff.get(2).run();
will result in :
Hallo
2 + 2 = 4
Hallo
This is a test
2 + 2 = 4
When you put variables or Passing Parameters in those runnable methods, they need to be effectively final or you pass them in a container.
You can re-run each method.
And within those Methods you can execute other methods.
NOTE:
If you want to have return Parameters you could do the same with Callable and than ".call()" instead of run.
EDIT:
Under the assumption you mean character Check or something like that
Example for charaCheck passable Method With Interface:
public interface CharacterChecker{
//is a template returns boolean, need a String param
public boolean call(String chara);
}
A method that executes a passes method of the type of "CHaracterChecker"
public static void excecutePassedMethod(CharacterChecker checker, String chara) {
System.out.println(chara + ": " + checker.call(chara));
}
Two different implementations of a "Character Checker"
CharacterChecker goodChecker = new CharacterChecker() {
#Override
public boolean call(String chara) {
return "good".equals(chara);
}
};
CharacterChecker lazyCheker = new CharacterChecker() {
#Override
public boolean call(String chara) {
return "lazy".equals(chara);
}
};
The Methods that are Passed the "method" (More like anonymos class object with the method)
excecutePassedMethod(goodChecker, "bad");
excecutePassedMethod(goodChecker, "good");
excecutePassedMethod(goodChecker, "jolly");
excecutePassedMethod(lazyCheker, "frisky");
excecutePassedMethod(lazyCheker, "lazy");
result will be:
bad: false
good: true
jolly: false
frisky: false
lazy: true
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.
I'm trying to implement stopwatch class that will wrap all the required methods that i'm trying to measure
The main purpose is to create an framwork that when ever you want to measure the execution time of a method you will change the exiting code from:
<Classname> x = A();
or
A();
To:
<Classname> x = PSW.startWatch(MethodToWatch.B).invoke("123123123", A());
or
PSW.startWatch(MethodToWatch.B).invoke("123123123", A());
This is the code:
public class PerformanceStopWatch {
private long start;
private long end;
private String uniqueID;
private MethodToWatch methodName;
public enum MethodToWatch {
A,
B
}
public PerformanceStopWatch startWatch(MethodToWatch methodName) {
this.methodName = methodName;
start();
return this;
}
public void invoke(String uniqeID) {
this.uniqueID = uniqeID;
stop();
}
public void invoke(UUID machineId, void a) {
invoke(machineId);
}
private void start() {
start = System.nanoTime();
}
private void stop() {
end = System.nanoTime();
System.out.println("[PerformanceStopWatch|"+methodName.name()+"] - Unique ID: "+ uniqueID + " Took: <"+(end-start)+"> Nanosec");
}
}
public void a() {
PerformanceStopWatch PSW = new PerformanceStopWatch();
..
..
..
PSW.startWatch(MethodToWatch.B).invoke("123123123", b());
}
public void b() {
...
...
..
}
The problem is that the compiler dose not allow me to use
public void invoke(UUID machineId, void a) {
}
void is illegle type.
any idea?
You can try Void insteed of void (Capital V) as the second one is not a type in strict sense. Void on the other hand is.
But in general if you want to invoke with "void" you simply ommit arguments (talking about reflection here)
EDIT: to your comment
public void invoke(UUID machineId, Void a) { //note the capital V
invoke(machineId);
}
Will compile just fine, but I dont see any usable usecase for such method signature.
It looks like you want to pass a method to the invoke() method. Since the method you are passing returns nothing and has no arguments, you should use Runnable interface :
public void invoke(UUID machineId, Runnable a) {
invoke(machineId);
a.run();
}
and
PSW.startWatch(MethodToWatch.B).invoke("123123123", () -> {b();});
or (if you are not using Java 8) :
PSW.startWatch(MethodToWatch.B).invoke("123123123",
new Runnable() {
public void run() {
b();
}
});
What exactly do you want to do? There are no objects or values of type void, so if it would have been allowed, you would not be able to call the method.
Maybe what you want is to be able to pass an object of any type. In this case you can use Object:
public void invoke(UUID machineId, Object a) {
invoke(machineId);
}
Since every class is a subclass of Object, now you can pass any object as the second argument to this method, including arrays. You can also pass primitive types (they will be wrapped to their corresponding wrapper class).
Is it possible through some method to assign a function to a variable in Java, like in PHP or JavaScript?
...Or does this area works on a different way when it comes to Java?
In Java you have Method and MethodHandles which can invoke a method via reflection but that is not supported in the language yet.
In Java 8, you will be able to use references to methods.
In today's java, no you can't.
The nearest you have is the interface : you don't store a function but the implementation of an interface defining the wanted function.
A typical example is the implementation of the Comparator interface :
Comparator<ProductSearchResult> c = new Comparator<ProductSearchResult>() {
public int compare(ProductSearchResult result1, ProductSearchResult result2) {
return result1.product.getRsId().compareTo(result2.product.getRsId());
}
};
Collections.sort(groupResults, c); // I pass a function, wrapped in my Comparator implementation
The nearest you have are inner classes combined with interfaces. These can carry not only one but many functions (methods) that can be delegated back to the master class methods if preferred. But this solution may easily be too heavyweight:
class Main {
interface X {
void doX();
}
class Ref1 implements X {
void doX() { doA(); };
}
class Ref2 implements X {
void doX() { doB(); };
}
void doA() { };
void doB() { };
void demo() {
X x = new Ref1();
x.doX();
}
}
This simulates something similar to Lambdas ... (you'll need a little more casting if you use anything other than Strings, but I'm keeping the example brief) ...
public class MyTest {
public static void main(String[] args) {
Lambda l = new Lambda() { public Object func(Object x)
{ return "Hello " + x; }
};
System.out.println(l.func("Bob"));
System.out.println(nowTryFromMethod(l));
System.out.println((new Lambda() { public Object func(Object x)
{ return "Goodbye " + x; }
}).func("Harry"));
}
private static Object nowTryFromMethod(Lambda l) {
return l.func("Jerry");
}
}
class Lambda {
public Object func(Object x) { return null; }
}
Output:
Hello Bob
Hello Jerry
Goodbye Harry
Update
Java supports reference to functions which is called Lambda from version 1.8
Java does NOT support that.
However, you can do that in JVM-Languages very comfortably, e.g. in Groovy.
Or you take a look at the command-pattern.