[wp_ad_camp_5]
This post demonstrates how to limit the depth of Inheritance in your codes. We will use a class InheritanceUtils from Apache Commons Lang.
Inheritance is Evil
Yes, inheritance is evil. If we subclass too much in our code base, sooner or later things become too difficult to manage. Maintenance and code refactor nightmares ensue.
Good thing there is Composition! However, we’ll not discuss it here.
Example Codes
Okay, let’s say we have an existing API that uses too much inheritance. We modified a “common” generic class (or abstract class) to perform the inheritance depth check internally.
We have an interface for a translator. Other codes “uses” a translator by invoking the process method.
1 2 3 4 5 | package com.turreta.apache.commons.lang.inheritance; public interface Translator { void process(); } |
[wp_ad_camp_4]
We have a GenericTranslator which is an abstract class. It defines the life-cycle of a translator.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | package com.turreta.apache.commons.lang.inheritance; import org.apache.commons.lang3.reflect.InheritanceUtils; public abstract class GenericTranslator implements Translator { /** * Main method invoked from one location in your API */ public void process() { this.translateInternal(); } /** * Method template */ private void translateInternal() { checkInheritance(); translate(); } /** * Method that must be overridden */ protected abstract void translate(); /** * Limit subclasses. * * Only direct descendant allowed. */ private void checkInheritance() { int oneLevelFromLanguageTranslator = InheritanceUtils.distance( this.getClass(), GenericTranslator.class); if(oneLevelFromLanguageTranslator != 1) { System.out.println(String.format("Subclass NOT OK! Inheritance level %d ", oneLevelFromLanguageTranslator)); throw new RuntimeException( "Only direct descendants are allowed for GenericTranslator!"); } System.out.println(String.format("Subclass ok! Inheritance level %d ", oneLevelFromLanguageTranslator)); } } |
Then, we have two implementations. We’ll use these classes to test our inheritance level check.
Direct Descendant to Generic Translator
[wp_ad_camp_3]
1 2 3 4 5 6 7 8 | package com.turreta.apache.commons.lang.inheritance; public class EnglishTranslator extends GenericTranslator { @Override public void translate() { System.out.println("English Language translator"); } } |
Descendant of a Descendant
1 2 3 4 5 6 7 8 9 | package com.turreta.apache.commons.lang.inheritance; public class SingaporeEnglishTranslator extends EnglishTranslator { @Override public void translate() { System.out.println("Singapore English translator"); } } |
Testing
[wp_ad_camp_2]
1 2 3 4 5 6 7 8 9 10 11 | import org.apache.commons.lang3.reflect.InheritanceUtils; public class InheritanceUtilsDemo { public static void main(String[] args) { Translator t1 = new EnglishTranslator(); t1.process(); Translator t2 = new SingaporeEnglishTranslator(); t2.process(); } } |
This outputs:
[wp_ad_camp_1]
References
- Apache Common Lang
- Method Template Design Pattern – https://www.youtube.com/watch?v=aR1B8MlwbRI
- Composition