What is the cleanest way in Java to write two versions of the same class where each has a different superclass? By cleanest I mean DRY (least duplicated code). The two classes will have similar but different names and the same code.
The application is Android: class MyActivity extends ActionBarActivity. Class MyActivity34 (for API level 3/4) extends Activity but has the same code as MyActivity. I don't want to keep two copies of everything (in C++ I would use the preprocessor for this). Changing the superclasses is not an option.
Thanks.
Note: The ActionBarActivity class can't be used at API level 3 or 4 (runtime error), so MyActivity34 can't have it anywhere in the inheritance path.
I would probably say your best bet is to use composition to encapsulate any duplicate code. Create a class which contains all the shared code and call it from the MyActivity and MyActivity34 classes. Often composition is better/cleaner than strange inheritance structures.
Create an interface ,say, MyCommonActivityInterface
with all the methods
public interface MyCommonActivityInterface {
public void sayHello();
public void sayGoodbye();
}
Create a common activity with all the code
public class MyCommonActivity implements MyCommonActivityInterface {
...
public void sayHello() {Log.d("MyCommonActivity", "says hello")};
public void sayGoodbye() {Log.d("MyCommonActivity", "says goodbye")};
...
}
Now you can reuse the common code in both Activities
public class MyActivity34 extends Activity {
MyCommonActivityInterface common = new MyCommonActivity();
public void sayHello() {common.sayHello()};
public void sayGoodbye() {common.sayGoodbye()};
}
public class MyActivity extends ActionBarActivity {
MyCommonActivityInterface common = new MyCommonActivity();
public void sayHello() {common.sayHello()};
public void sayGoodbye() {common.sayGoodbye()};
}
Well actually the interface can be omitted, but will come handy if you need to swap between alternatives or the like.
I have become really impressed by the powers of Dependency Injection, which can make these kind of things much cleaner.
There is a library called Dagger that adds DI support for android. It has a somewhat steep learning curve but for me it was all worth it.
In this example you would be able to do stuff like:
@Singleton
public class MyCommonActivity {
// Example with context to show that it will be automagically injected
@Inject
public MyCommonActivity(@ForActivity Context context) {}
...
public void sayHello() {Log.d("MyCommonActivity", "says hello")};
public void sayGoodbye() {Log.d("MyCommonActivity", "says goodbye")};
...
}
public class MyActivity34 extends Activity {
@Inject MyCommonActivity common;
public void sayHello() {common.sayHello()};
public void sayGoodbye() {common.sayGoodbye()};
}
public class MyActivity extends ActionBarActivity {
@Inject MyCommonActivity common;
public void sayHello() {common.sayHello()};
public void sayGoodbye() {common.sayGoodbye()};
}
With a lot of independent classes of code, where some depends on others, or needs a Context object etc,.. simply adding a @Inject line when and where ever you need it saves many lines of code!
And while we are add it, have a look at ButterKnife , much simpler but also only works for injecting Views. Still pretty darn powerful and neat.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.