The lack of Java template inheritance causes serious problems with code duplication in Android. Any solutions?

This is a feature of Android.

I am extracting all my actions in Android from a custom class that provides a nice and clean place to host the common code used by all layouts in the application, especially for some common setContentView () override code that injects layouts into my layouts. So this is what a typical hierarchy looks like:

MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity 

For one of my applications, I need Google Maps support. So I tried turning MyBaseClass into a / generic pattern so that I could do something like:

 MyActivity extends MyBaseClass<MapActivity> -> MyBaseClass<T> extends T -> T 

Which, of course, could not be compiled, because Java / generics templates are not as useful as C ++ templates, as I discovered shortly after the attempt. So I created a whole separate class as a workaround:

 MyActivity extends MyBaseMapClass -> MyBaseMapClass extends MapActivity -> MapActivity 

And copied all the code from MyBaseClass to MyBaseMapClass. The code is identical, with the exception of a few minor changes related to import. It works, but this is hardly a good solution.

I crossed my fingers that the end of the problem would be higher, and I would never have to visit it again.

Unfortunately, I'm starting to experiment with a fragment and a combination of actions with a much more complex base class, and the problem of duplicating code with the above becomes a serious problem. Every time I make changes to one file, I must remember that it clones it to other files, and development moves fast enough, and I quickly exit synchronization.

Activity, MapActivity, FragmentActivity, ListActivity, PreferenceActivity, etc. Do I need to create a separate derived class for each of the ones I want to use? I hope not, and for this reason I have already limited my derivations to begin with (some of my actions do not have certain functions as a result). The problem is even more upset by the fact that I sometimes use two separate base classes (where some actions should inflate even more views into the layout, but not all actions should do this):

 MyActivity extends MyBaseClass -> MyBaseClass extends Activity -> Activity MyActivity2 extends AnotherBaseClass -> AnotherBaseClass extends MyBaseClass -> MyBaseClass extends Activity -> Activity 

If I want to use the code for AnotherBaseClass in Maps, I not only need to create MyBaseMapClass, but also AnotherBaseMapClass and copy the code. At the moment, I'm up to four classes, where two classes make up a couple of thousand lines of cloned code. The replicated code bothers me because it makes maintenance and development much more complicated.

The output of Android classes is complex, such as findViewById (), which are part of the base Activity class. This is important because I am not sure how to write an interface or composition without encountering the same problems that I just described.

Has anyone here encountered this problem and come up with a workable solution?

+6
source share
3 answers

Why don't you just create a helper class with a static function like styleActivity(Activity a) ? In this case, this is an easier solution than using inheritance.

+2
source

So basically you want multiple inheritance which Java does not support.

You can model multiple inheritance

 interface MyBaseInterface foo(); bar(); class MyBaseClass implements MyBaseInterface foo(){ ... }; bar(){ ... }; class MyMapActivity extends MapActivity implements MyBaseInterface // boiler plate c&p MyBaseClass base; foo(){ return base.foo(); } bar(){ return base.bar(); } 

However, what is the reason MyMapActivity should implements MyBaseInterface ? Probably not.

Maybe it's good enough

 class MyBaseClass foo(){ ... }; bar(){ ... }; class MyMapActivity extends MapActivity public final MyBaseClass base; 

so every time you need to treat MyMapActivity as MyBaseClass , just use the base variable.

  activity.base.foo(); 

for abstract / overridden methods

 class MyMapActivity extends MapActivity public final MyBaseClass base = new MyBaseClass() { foo(){ do my foo thing; } } 
0
source

Actually, your own operator "Java templates / generics are not as useful as C ++ templates" is the best answer to your question :).

Constructs like class MyClass<T> extends T are unfortunately illegal in java. And even if they are legal, they will mean the same thing as the class MyClass extends Object , since parameterized types are erased in bytecode. (read about erasing the type http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20erasure? )

I would stick with the Helper class proposed by SimonSays in another answer.

 class MyHelper<T extends Activity> { final T activity; public MyHelper(T activity) { this.activity = activity; //here you can access Acitivities methods on T object //and compiler will not say a single bad word ;) //unfotunately only public methods activity.getLayoutInflater(); } public T getActivity() { return activity; } } 
0
source

All Articles