Partial override in Java (or dynamic override on overload)
If I have a parent-child that defines some method .foo () like this:
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Function");
}
}
class Child extends Parent {
public void foo(Child arg) {
System.out.println("foo in ChildFunction");
}
}
When I called them like this:
Child f = new Child();
Parent g = f;
f.foo(new Parent());
f.foo(new Child());
g.foo(new Parent());
g.foo(new Child());
output:
foo in Parent
foo in Child
foo in Parent
foo in Parent
But I want this output:
foo in Parent
foo in Child
foo in Parent
foo in Child
I have a Child class that extends the parent's class. In the Child class, I want to "partially override" the parent foo()
, that is, if the argument arg
is of type Child, then Child foo()
is called instead of Parent foo()
.
It works Well when I called f.foo(...)
as a Child; but if I reference it from its Parent alias as in g.foo(...)
then the parent foo(..)
is called regardless of the type arg
.
As I understand it, I do not expect what is expected, because method overloading in Java is early binding (i.e. solved statically at compile time) and method overriding is late binding (i.e. dynamic dynamics at compile time), and since I am a defined function with technically a different type of argument, I am technically overloading the parent class definition with a clear definition rather than overriding it. But what I want to do is conceptually "partially override" when the argument foo()
is a subclass of the parent argument foo()
.
I know that I can define a bucket override foo(Parent arg)
on Child that checks if the actual arg type is parent or child and pass it in correctly, but if I have twenty Children it would be a lot of duplication of unsafe type code.
In my actual code, Parent is an abstract class named "Function" that just throws NotImplementedException()
. Children include "Polynomial", "Logarithmic", etc. And .foo () includes things like Child.add (Child), Child.intersectionsWith (Child), etc. Not every combination of Child.foo (OtherChild) is solvable, and in fact, not even all Child.foo (Child) are solvable. So my best bet is to define all undefined (i.e. throw NotImplementedException) and then only define those that can be defined.
So the question is: is there a way to override only a portion of the parent foo ()? Or is there a better way to do what I want to do?
EDIT :
@Zeiss: if i use Double Dispatch like so:
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Parent");
}
}
class Child extends Parent {
public void foo(Parent arg) {
System.out.println("foo in Child(Parent)");
arg.foo(this);
}
public void foo(Child arg) {
System.out.println("foo in Child(Child)");
}
}
I got infinite recursion:
(stack):
StackOverflowError: ...
...
at sketch_apr25a$Child.foo(sketch_apr25a.java:35)
...
(output):
...
foo in Child(Parent)
...
when doing g.foo(new Child());
. The rest seems fine as the output is:
foo in Child(Parent)
foo in Parent
foo in Child(Child)
foo in Child(Parent)
foo in Parent
foo in Child(Parent)
(infinite recursion follows)
Why is this happening? g is the parent alias, but does it refer to Child foo (Parent)?
a source to share
Isn't this used for Double Dispatching ?
Update:
class Function {
public void add(Function f) {
f.addMe(this);
}
public void addMe(Function f) {
// Default case
throw NotImplementedException();
}
public void addMe(Logarithmic log) {
// Code that handles the real
}
}
class Logarithmic extends Function {
// This object supports adding
public void add(Function f) {
f.addMe(this);
}
}
Logarithmic log = new Logarithmic();
log.add(new Function());
log.add(new Logarithmic());
Function f = log;
f.add(new Function());
f.add(new Logarithmic());
a source to share
I got it to work by explicitly overriding foo(Parent arg)
in Child
like this -
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Parent");
}
}
class Child extends Parent {
@Override
public void foo(Parent arg) {
System.out.println("foo in Child(Parent)");
if (arg instanceof Child) {
foo((Child)arg);
} else {
super.foo(arg);
}
}
public void foo(Child arg) {
System.out.println("foo in Child(Child)");
}
}
It seems like logic
I want to "partially override" the parent foo (), that is, if the arg type argument is Child, then Child is called Child foo () instead of fent ().
Instead of "partially overriding" a method, you really need to override the method.
a source to share