I am afraid you can-t implement your classsystem without codeduplication in android/java.
However you can minimize codeduplication if you combine special intermediate derived class with
composite helper object. This is called the Decorator_pattern:
class ActivityHelper {
Activity owner;
public ActivityHelper(Activity owner){/*...*/}
onStart(/*...*/){/*...*/}
}
public class MyTabActivityBase extends TabActivity {
private ActivityHelper helper;
public MyTabActivityBase(/*...*/) {
this.helper = new ActivityHelper(this);
}
protected void onStart() {
super.onStart();
this.helper.onStart();
}
// the same for onStop, onSaveInstanceState, onRestoreInstanceState,...
}
Public class MySpecialTabActivity extends MyTabActivityBase {
// non helper logic goes here ....
}
so every base class you create an intermediate baseclass that delegates its calls to the helper.
The intermediate basesclasses are identical except the the baseclase where they inherit from.
The SAM approach is actually somewhat similar to what Scala (and C++11) do with anonymous functions (created with Scala's =>
operator or C++11's []()
(lambda) syntax).
The first question to answer on the Java side is whether to have the return type of a lambda statement be a new primitve type, like int
or byte
, or an object type of some sort. In Scala, there are no primitive types -- even an integer is an object of class Int
-- and functions are no different, being objects of class Function1
, Function2
, and so forth, depending on the number of arguments the function takes.
C++11, ruby and python similarly have lambda expressions which return an object which is callable in explicit or implicit way. The returned object has some standard method (such as #call
which can be used to call it as a function. C++11, for instance, uses a std::function
type which overloads operator()
so that calls of the object's call method even look like function calls, textually. :-)
Where the new proposal for Java gets messy is in the use of structural typing to allow assigning such a method to another object, such as a Comparator
which has a single main method with a different name. While this is conceptually icky in some ways, it does mean that the resulting object can be passed to existing functions which take an object to represent a callback, a comparator, and so on, and expect to be able to call a well-defined single method such as #compare
or #callback
. C++'s trick of overriding operator()
neatly dodged this issue even before C++11, since all such callback options were callable the same way, and thus the STL required no adjustment to allow C++11 lambdas to be used with sort
and so on. Java, not having used a standard naming for such objects in the past (perhaps because no trick like operator overloading made a single approach obvious), isn't so lucky, so this hack prevents them from having to change a whole lot of existing APIs.
Best Answer
Multiple dispatch is not (always) the same as function overloading, although they do bear some similarities. And Java does not support multiple dispatch.
In statically typed languages, including Java, the biggest difference between dispatch and overloading is that overloading is based on the static type of parameters (i.e. the choice of which method is actually called is decided compile-time), while dispatch is based on the dynamic types (i.e. the decision is made runtime). (Such languages usually don't support multiple dispatch.)
But then again, this may be a question of terminology. In dynamically typed languages, dispatch and overloading indeed seem to boil down to the same thing.