1- Checks that classes are designed for inheritance.
1+
2+ < h2 > DesignForExtension</ h2 >
3+
4+ < div >
5+ < h3 > < a name ="Description "> </ a > Description</ h3 >
6+
7+ < p >
8+ The check finds classes that are designed for extension (subclass creation).
9+ </ p >
10+
11+ < p >
12+ Nothing wrong could be with founded classes.
13+ This check makes sense only for library project (not an application projects)
14+ which care of ideal OOP-design to make sure that class works in all cases even misusage.
15+ Even in library projects this check most likely will find classes that are designed
16+ for extension by somebody. User needs to use suppressions extensively to got a benefit from
17+ this check, and keep in suppressions all confirmed/known classes that are deigned for
18+ inheritance intentionally to let the check catch only new classes, and bring this to
19+ team/user attention.
20+ </ p >
21+
22+ < p >
23+ ATTENTION: Only user can decide whether a class is designed for extension or not.
24+ The check just shows all classes which are possibly designed for extension.
25+ If smth inappropriate is found please use suppression.
26+ </ p >
27+
28+ < p >
29+ ATTENTION: If the method which can be overridden in a subclass has a javadoc comment
30+ (a good practise is to explain its self-use of overridable methods) the check will not
31+ rise a violation. The violation can also be skipped if the method which can be overridden
32+ in a subclass has one or more annotations that are specified in ignoredAnnotations
33+ option. Note, that by default @Override annotation is not included in the
34+ ignoredAnnotations set as in a subclass the method which has the annotation can also be
35+ overridden in its subclass.
36+ </ p >
37+
38+ < p >
39+ Problem is described at "Effective Java, 2nd Edition by Josh Bloch" book, chapter "Item 17: Design and document for inheritance or else prohibit it".
40+ </ p >
41+
42+ < p >
43+ Some quotes from book:
44+ </ p >
45+
46+ < blockquote > The class must document its self-use of overridable methods.
47+ By convention, a method that invokes overridable methods contains a description
48+ of these invocations at the end of its documentation comment. The description
49+ begins with the phrase “This implementation.”
50+ </ blockquote >
51+
52+ < blockquote > The best solution to this problem is to prohibit subclassing in classes that
53+ are not designed and documented to be safely subclassed.
54+ </ blockquote >
55+
56+ < blockquote > If a concrete class does not implement a standard interface, then you may
57+ inconvenience some programmers by prohibiting inheritance. If you feel that you
58+ must allow inheritance from such a class, one reasonable approach is to ensure
59+ that the class never invokes any of its overridable methods and to document this
60+ fact. In other words, eliminate the class’s self-use of overridable methods entirely.
61+ In doing so, you’ll create a class that is reasonably safe to subclass. Overriding a
62+ method will never affect the behavior of any other method.
63+ </ blockquote >
64+
65+ < p >
66+ The check finds classes that have overridable methods (public or protected methods
67+ that are non-static, not-final, non-abstract) and have non-empty implementation.
68+ </ p >
69+
70+
71+ < p >
72+ Rationale: This library design style protects superclasses against
73+ being broken by subclasses. The downside is that subclasses are
74+ limited in their flexibility, in particular they cannot prevent
75+ execution of code in the superclass, but that also means that
76+ subclasses cannot corrupt the state of the superclass by forgetting
77+ to call the superclass's method.
78+ </ p >
79+
80+ < p >
81+ More specifically,
82+ it enforces a programming style where superclasses provide empty
83+ "hooks" that can be implemented by subclasses.
84+ </ p >
85+
86+ < p >
87+ Example of code that cause violation as it is designed for extension:
88+ </ p >
89+
90+ < div class ="source ">
91+ < pre > public abstract class Plant {
92+ private String roots;
93+ private String trunk;
94+
95+ protected void validate() {
96+ if (roots == null) throw new IllegalArgumentException("No roots!");
97+ if (trunk == null) throw new IllegalArgumentException("No trunk!");
98+ }
99+
100+ public abstract void grow();
101+ }
102+
103+ public class Tree extends Plant {
104+ private List leaves;
105+
106+ @Overrides
107+ protected void validate() {
108+ super.validate();
109+ if (leaves == null) throw new IllegalArgumentException("No leaves!");
110+ }
111+
112+ public void grow() {
113+ validate();
114+ }
115+ }
116+ </ pre > </ div >
117+
118+ < p >
119+ Example of code without violation:
120+ </ p >
121+
122+ < div class ="source ">
123+ < pre > public abstract class Plant {
124+ private String roots;
125+ private String trunk;
126+
127+ private void validate() {
128+ if (roots == null) throw new IllegalArgumentException("No roots!");
129+ if (trunk == null) throw new IllegalArgumentException("No trunk!");
130+ validateEx();
131+ }
132+
133+ protected void validateEx() { }
134+
135+ public abstract void grow();
136+ }
137+ </ pre > </ div >
138+ </ div >
139+
140+
141+ < div >
142+ < h3 > < a name ="Properties "> </ a > Properties</ h3 >
143+
144+ < table class ="bodyTable " border ="0 ">
145+
146+ < tbody > < tr class ="a ">
147+
148+ < th > name</ th >
149+
150+ < th > description</ th >
151+
152+ < th > type</ th >
153+
154+ < th > default value</ th >
155+ </ tr >
156+
157+ < tr class ="b ">
158+
159+ < td > ignoredAnnotations</ td >
160+
161+ < td >
162+ Annotations which allow the check to skip the method from validation.
163+ </ td >
164+
165+ < td > String Set</ td >
166+
167+ < td > < tt > Test, Before, After, BeforeClass, AfterClass</ tt > </ td >
168+ </ tr >
169+ </ tbody > </ table >
170+ </ div >
171+
172+
173+ < div class ="section ">
174+ < h3 > < a name ="Examples "> </ a > Examples</ h3 >
175+
176+ < p >
177+ To configure the check:
178+ </ p >
179+
180+
181+ < div class ="source ">
182+ < pre > <module name="DesignForExtension"/>
183+ </ pre > </ div >
184+
185+
186+ < p >
187+ To configure the check to allow methods which have @Override and @Test annotations to be
188+ designed for extension.
189+ </ p >
190+
191+
192+ < div class ="source ">
193+ < pre > <module name="DesignForExtension">
194+ <property name="ignoredAnnotations" value="Override, Test"/>
195+ </module>
196+ </ pre > </ div >
197+
198+
199+ < div class ="source ">
200+ < pre > public class A extends B {
201+ @Override
202+ public int foo() {
203+ return 2;
204+ }
205+
206+ public int foo2() {return 8;} // violation
207+ }
208+
209+ public class B {
210+ /**
211+ * This implementation ...
212+ @return some int value.
213+ */
214+ public int foo() {
215+ return 1;
216+ }
217+
218+ public int foo3() {return 3;} // violation
219+ }
220+
221+ public class FooTest {
222+ @Test
223+ public void testFoo() {
224+ final B b = new A();
225+ assertEquals(2, b.foo());
226+ }
227+
228+ public int foo4() {return 4;} // violation
229+ }
230+ </ pre > </ div >
231+ </ div >
232+
233+
234+
0 commit comments