Newer
Older
<chapter annotations="slide" version="5.1" xml:id="sw1ChapterInheritance"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns="http://docbook.org/ns/transclusion"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<figure xml:id="sd1_inherit_fig_guessWho">
<title>Guess who's inheriting the money</title>
<mediaobject>
<imageobject>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sd1_inherit_fig_biologicalInherit">
<title>Biology and inheritance</title>
<mediaobject>
<imageobject>
</imageobject>
</mediaobject>
</figure>
<title>Duplicate code</title>
<informaltable border="0">
<tr>
<td valign="top"><programlisting language="none">public class Rectangle{
// Center coordinate
<emphasis role="red">private double x</emphasis>; <co
linkends="sda_inherit_fig_DuplicateCode-1"
xml:id="sda_inherit_fig_DuplicateCode-1-co"/>
<emphasis role="red">private double y</emphasis>;
<emphasis role="red">public void move
(double dx, double dy){</emphasis> <co
linkends="sda_inherit_fig_DuplicateCode-2"
xml:id="sda_inherit_fig_DuplicateCode-2-co"/>
<emphasis role="red">x += dx;
y += dy;
}</emphasis>
private double width, height; <co linkends="sda_inherit_fig_DuplicateCode-3"
xml:id="sda_inherit_fig_DuplicateCode-3-co"/> ...
}</programlisting></td>
<td valign="top"><programlisting language="none">public class Circle {
<emphasis role="red">private double x</emphasis>; <coref
linkend="sda_inherit_fig_DuplicateCode-1-co"/>
<emphasis role="red">private double y</emphasis>;
<emphasis role="red">public void move
(double dx, double dy){</emphasis> <coref
linkend="sda_inherit_fig_DuplicateCode-2-co"/>
<emphasis role="red">x += dx;
y += dy;
}</emphasis>
private double radius; <coref linkend="sda_inherit_fig_DuplicateCode-3-co"/> ...
}</programlisting></td>
</tr>
</informaltable>
<calloutlist role="slideExclude">
<callout arearefs="sda_inherit_fig_DuplicateCode-1-co"
xml:id="sda_inherit_fig_DuplicateCode-1">
<para>The center coordinate (<code language="java">x</code>|<code
language="java">y)</code> appears both in
<classname>Rectangle</classname> and
<classname>Circle</classname>.</para>
</callout>
<callout arearefs="sda_inherit_fig_DuplicateCode-2-co"
xml:id="sda_inherit_fig_DuplicateCode-2">
<para>The move(...) method is being defined <emphasis
role="bold">identically</emphasis> both in
<classname>Rectangle</classname> and
<classname>Circle</classname>!</para>
</callout>
<callout arearefs="sda_inherit_fig_DuplicateCode-3-co"
xml:id="sda_inherit_fig_DuplicateCode-3">
<itemizedlist>
<listitem>
<para><property>width</property> and <property>height</property>
only appear in class <classname>Rectangle</classname>.</para>
</listitem>
<listitem>
<para><property>radius</property> only appears in class
Circle.</para>
</listitem>
</itemizedlist>
</callout>
</calloutlist>
</figure>
<figure xml:id="sda_inherit_fig_ideaFactorOutCommonCode">
<title>Idea: Centralize common code</title>
<itemizedlist>
<listitem>
<para>Create a parent class <classname>Shape</classname> containing
common code portions.</para>
</listitem>
<listitem>
<para>Relate both <classname>Rectangle</classname> and
<classname>Circle</classname> to <classname>Shape</classname>.</para>
</listitem>
</itemizedlist>
</figure>
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<figure xml:id="sda_inherit_fig_shapeCommonSpecific">
<title>Common and specific properties</title>
<informaltable border="0">
<colgroup width="40%"/>
<colgroup width="20%"/>
<colgroup width="40%"/>
<tr>
<th align="center" colspan="3" valign="top">Common
<classname>Rectangle</classname> and <classname>Circle</classname>
attributes:</th>
</tr>
<tr>
<td valign="top"/>
<td valign="top"><programlisting language="java">double x;
double y;</programlisting></td>
<td valign="top"/>
</tr>
<tr>
<th align="center" valign="top"><classname>Rectangle</classname>
attributes</th>
<td/>
<th align="center" valign="top"><classname>Circle</classname>
attributes</th>
</tr>
<tr>
<td valign="top"><programlisting language="java">double width;
double height;</programlisting></td>
<td/>
<td valign="top"><programlisting language="java">double radius;</programlisting></td>
</tr>
</informaltable>
</figure>
<figure xml:id="sda_inherit_fig_shapeInheritPrinciple">
<title>Basic shape inheritance</title>
<mediaobject>
<imageobject>
<imagedata fileref="Fig/shapeBasicInherit.multi.svg"/>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sda_inherit_fig_intro">
<title>Inheritance</title>
<itemizedlist>
<listitem>
<para>Derived classes inherit state and behaviour.</para>
</listitem>
<listitem>
<para>Refinement, specialization.</para>
</listitem>
<listitem>
<para>A rectangle <emphasis role="red">is a</emphasis>
shape.</para>
<para>A circle <emphasis role="red">is a</emphasis> shape.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</figure>
<figure xml:id="sda_inherit_fig_shapeSimpleImplement">
<title>Implementing <classname>Shape</classname> hierarchy</title>
<informaltable border="0">
<colgroup width="25%"/>
<colgroup width="25%"/>
<colgroup width="25%"/>
<colgroup width="25%"/>
<tr>
<td valign="top"/>
<td colspan="2" valign="top"><programlisting language="java">public class Shape {
private double x, y;
}</programlisting></td>
<td valign="top"/>
</tr>
<tr>
<td colspan="2" valign="top"><programlisting language="java">public class Rectangle extends Shape {
private double width;
private double height;
}</programlisting></td>
<td colspan="2" valign="top"><programlisting language="java">public class Circle extends Shape {
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
private double radius;
}</programlisting></td>
</tr>
</informaltable>
</figure>
<figure xml:id="sda_inherit_fig_createShapesInstances">
<title>Creating instances</title>
<programlisting language="java">final double x = 2, y = 3;
final Shape shape = new Shape(x, y);
final double width = 2, height = 5;
final Rectangle r = new Rectangle(x, y , width, height);
final double radius = 2.5;
final Circle circle = new Circle(x, y , radius);</programlisting>
</figure>
<figure xml:id="sda_inherit_fig_createShapesConstruct">
<title><classname>Shape</classname> constructor</title>
<programlisting language="java">/**
* Creating a shape located at center coordinate.
* @param x The center's x component.
* @param y The center's y component.
*/
public Shape(double x,double y) {
this.x = x;
this.y = y;
}</programlisting>
</figure>
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
<figure xml:id="sda_inherit_fig_createRectangle">
<title>Creating <classname>Rectangle</classname> instances</title>
<programlisting language="java">final Rectangle r =
new Rectangle(x, y <co linkends="sda_inherit_fig_createRectangle-1"
xml:id="sda_inherit_fig_createRectangle-1-co"/>,
width, height <co
linkends="sda_inherit_fig_createRectangle-2"
xml:id="sda_inherit_fig_createRectangle-2-co"/>);</programlisting>
<calloutlist>
<callout arearefs="sda_inherit_fig_createRectangle-1-co"
xml:id="sda_inherit_fig_createRectangle-1">
<para>Center coordinate components <quote>belonging</quote> to
superclass <classname>Shape</classname>.</para>
</callout>
<callout arearefs="sda_inherit_fig_createRectangle-2-co"
xml:id="sda_inherit_fig_createRectangle-2">
<para>width and height <quote>belonging</quote> to class
<classname>Rectangle</classname>.</para>
</callout>
</calloutlist>
<para>Solution: Nested constructor call. Coming soon ...</para>
</figure>
<figure xml:id="sda_inherit_fig_RectangleConstructor">
<title><classname>Rectangle</classname> constructor</title>
<programlisting language="java">/**
* Creating a rectangle at (x|y) of given width and height.
* @param x Center's x component.
* @param y Center's y component.
* @param width Rectangle's width.
* @param height Rectangle's height.
*/
public <link
xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/P/Sd1/Figure/ToString/src/main/java/de/hdm_stuttgart/mi/sd1/shape/model/Rectangle.java">Rectangle</link>(double x, double y,
double width, double height) {
super(x, y) <co linkends="sda_inherit_fig_RectangleConstructor-1"
xml:id="sda_inherit_fig_RectangleConstructor-1-co"/>;
this.width = width; this.height = height <co
linkends="sda_inherit_fig_RectangleConstructor-2"
xml:id="sda_inherit_fig_RectangleConstructor-2-co"/>;
}</programlisting>
<calloutlist role="slideExclude">
<callout arearefs="sda_inherit_fig_RectangleConstructor-1-co"
xml:id="sda_inherit_fig_RectangleConstructor-1">
<para>Passing center coordinate to superclass
<classname>Shape</classname>'s constructor.</para>
<note>
<para>This <emphasis>must</emphasis> be the first statement within
<classname>Rectangle</classname>'s constructor.</para>
</note>
</callout>
<callout arearefs="sda_inherit_fig_RectangleConstructor-2-co"
xml:id="sda_inherit_fig_RectangleConstructor-2">
<para>Processing <code language="java">width</code> and <code
language="java">height</code> in <quote>current</quote>
<classname>Rectangle</classname> constructor.</para>
</callout>
</calloutlist>
</figure>
<section xml:id="sd1_inherit_sect_overrideEquals">
<title>Overriding <methodname>equals()</methodname> and
<methodname>hashCode()</methodname></title>
<figure xml:id="sda_inherit_fig_ShapeEquals">
<title><classname>Shape</classname>.<methodname>equals()</methodname></title>
<programlisting language="java">public abstract class Shape {
...
@Override <co linkends="sda_inherit_fig_ShapeEquals-1"
xml:id="sda_inherit_fig_ShapeEquals-1-co"/> public boolean equals(final Object o) {
if (o instanceof Shape <emphasis role="red">s</emphasis> <co
linkends="sda_inherit_fig_ShapeEquals-2"
xml:id="sda_inherit_fig_ShapeEquals-2-co"/>) {
return x == <emphasis role="red">s</emphasis>.x && y == <emphasis
role="red">s</emphasis>.y; <co
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
linkends="sda_inherit_fig_ShapeEquals-4"
xml:id="sda_inherit_fig_ShapeEquals-4-co"/>
} else {
return false; <co linkends="sda_inherit_fig_ShapeEquals-5"
xml:id="sda_inherit_fig_ShapeEquals-5-co"/>
} ...</programlisting>
<calloutlist role="slideExclude">
<callout arearefs="sda_inherit_fig_ShapeEquals-1-co"
xml:id="sda_inherit_fig_ShapeEquals-1">
<para>Promise: The current method overrides a superclass
method.</para>
</callout>
<callout arearefs="sda_inherit_fig_ShapeEquals-2-co"
xml:id="sda_inherit_fig_ShapeEquals-2">
<para>Other instance is a <classname>Shape</classname>
object?</para>
</callout>
<callout arearefs="sda_inherit_fig_ShapeEquals-4-co"
xml:id="sda_inherit_fig_ShapeEquals-4">
<para>Return <code language="java">true</code> if and only if both
center coordinate pairs are equal.</para>
</callout>
<callout arearefs="sda_inherit_fig_ShapeEquals-5-co"
xml:id="sda_inherit_fig_ShapeEquals-5">
<para>Other object distinct from class
<classname>Shape</classname>.</para>
</callout>
</calloutlist>
</figure>
<figure xml:id="sda_inherit_fig_RectangleEquals">
<title><classname>Rectangle</classname>.<methodname>equals()</methodname></title>
<programlisting language="java">public class Rectangle extends Shape {
...
@Override public boolean equals(final Object o) {
if (o instanceof Rectangle <emphasis role="red">r</emphasis>) {
return super.equals(o) <co linkends="sda_inherit_fig_RectangleEquals-1"
xml:id="sda_inherit_fig_RectangleEquals-1-co"/> &&
width == <emphasis role="red">r</emphasis>.width && height == <emphasis
role="red">r</emphasis>.height <co
linkends="sda_inherit_fig_RectangleEquals-2"
xml:id="sda_inherit_fig_RectangleEquals-2-co"/>;
} else {
return false;
} ...</programlisting>
<calloutlist role="slideExclude">
<callout arearefs="sda_inherit_fig_RectangleEquals-1-co"
xml:id="sda_inherit_fig_RectangleEquals-1">
<para>Including superclass method
<classname>Shape</classname>.<methodname>equals()</methodname>.</para>
</callout>
<callout arearefs="sda_inherit_fig_RectangleEquals-2-co"
xml:id="sda_inherit_fig_RectangleEquals-2">
<para>Return <code language="java">true</code> if and only if both
<code language="java">width</code> and <code
language="java">height</code> pairs are equal.</para>
</callout>
</calloutlist>
</figure>
<qandaset defaultlabel="qanda" xml:id="sd1_qanda_stringEqualProblem">
<qandadiv>
<qandaentry>
<question>
<para>Consider the following snippet:</para>
<programlisting language="java">final Scanner scan = new Scanner(System.in));
do {
System.out.print("Please enter password: ");
final String password = scan.nextLine();
if (password == "secret") {
break; // Leave enclosing do ... while loop
} else {
System.out.println("Sorry, please try again");
}
} while (true);
System.out.println("You made it!");
<para>Describe the above code's intended behaviour. Will it
succeed? Execute the above code and provide a clue for correcting
the underlying flaw.</para>
</question>
<answer>
<para>The user is being asked for a password. Only when entering
<code>"secret"</code> access shall be granted.</para>
<para>Unfortunately comparing the user's input and the
corresponding password is seriously flawed:</para>
<programlisting language="java">...
if (password == "secret")
...</programlisting>
<para>On execution the string literal "secret" will be represented
as a <classname xlink:href="javaapi://String">String</classname>
object in memory. Each new user input string will be represented
as a <emphasis>different</emphasis> <classname
xlink:href="javaapi://String">String</classname> object in memory
as well.</para>
<para>Unfortunately the <quote>==</quote> operator only works as
expected for the eight built in primitive <xref
linkend="glo_Java"/> types. With respect to class instances
variables hold references to objects rather than to the objects'
values. The <quote>==</quote> operator compares for object
identity rather than for object equality.</para>
<para>Two different <classname
xlink:href="javaapi://String">String</classname> instances may off
course be equal with respect to their <quote>payload</quote>
namely the values they both represent. Comparing for object
equality rather than for object identity in <xref
linkend="glo_Java"/> requires using the
<methodname>equals(...)</methodname> method instead. A
prerequisite for this to work requires the class authors
xlink:href="javaapi://Object#equals(java.lang.Object)">Object.equals(Object
o)</methodname> method accordingly. This override does exist in
class <classname xlink:href="javaapi://String">String</classname>.
Within the given context we may thus simply use <methodname
xlink:href="javaapi://String#equals(java.lang.Object)">String.equals(Object
<programlisting language="none">final Scanner scan = new Scanner(System.in));
do {
System.out.print("Please enter password: ");
final String password = scan.nextLine();
<emphasis role="red">if (password.equals("secret"))</emphasis> {
break; // Leave enclosing do ... while loop
} else {
System.out.println("Sorry, please try again");
}
} while (true);
System.out.println("You made it!");
// ...</programlisting>
</answer>
</qandaentry>
</qandadiv>
</qandaset>
<qandaset defaultlabel="qanda" xml:id="sd1_qanda_enomNoEqualsRequired">
<title>Why is == correctly comparing <code language="java">enum</code>
instances?</title>
<qandadiv>
<qandaentry>
<question>
<para>The preceding exercise <xref
linkend="sd1_qanda_stringEqualProblem"/> told us to override
<methodname
xlink:href="javaapi://Object#equals(java.lang.Object)">Object.equals(Object
o)</methodname> when comparing different objects for equality. The
== operator on the other hand does compare for object identity
rather than semantic equality of objects based on their respective
attribute values. However comparing <code
language="java">Enum</code> instances for equality using the <code
language="java">==</code> operator seems to be sufficient<abbrev>
e.g.</abbrev>:</para>
<programlisting language="java">Day day = Day.Saturday;
// Sufficient using operator == ?
if (day == Day.FRIDAY) ...
// Or do we require equals?
if (day.equals(Day.FRIDAY)) ...</programlisting>
<para>Do we thus require an <methodname>equals(Object
o)</methodname> method in <code language="java">enum</code>
<classname>Day</classname> for comparisons? Give a precise
explanation.</para>
</question>
<answer>
<para>In case of <code language="java">enum</code> instances using
the <quote>==</quote> operator is sufficient. Due to the way <code
language="java">enum</code>'s are being constructed instance
language="java">private</code> constructor. It is thus impossible
creating new instances outside the respective <code
<para>Therefore for any two given <code
language="java">enum</code> instances both object identity and
equality of their respective values is being guaranteed to yield
the very same result:</para>
<programlisting language="none">MyEnum instance1 = MyEnum.x, // MyEnum representing
instance2 = MyEnum.y; // some enum type.
<emphasis role="red">objectIdentity</emphasis> = (instance1 == instance2), // Both boolean values will
<emphasis role="red">objectEquality</emphasis> = instance1.equals(instance2); // always be equal.</programlisting>
<para>As an aside: In case of <code language="java">null</code>
values using the <quote>==</quote> operator avoids
<classname>java.lang.NullPointerException</classname>
problems:</para>
<programlisting language="java">Day day = null;
if (day == Day.FRIDAY) ... // Just different, no problems
if (day.equals(Day.FRIDAY)) ... // Oops: NPE approaching ...</programlisting>
</answer>
</qandaentry>
</qandadiv>
</qandaset>
</section>
<section xml:id="sd1_inherit_sect_overrideToString">
<figure xml:id="sda_inherit_fig_shapeInstanceLog">
<title>Printing a <classname>Shape</classname>'s info</title>
<informaltable border="0">
<tr>
<th>Code</th>
<tr>
<td valign="top"><programlisting language="none">package inherit;
public class Run {
public static void main(String[] args) {
new Shape(<emphasis role="red">2.0</emphasis>, <emphasis role="red">3.0</emphasis>); // Center coordinates
System.out.println(shape); </programlisting></td>
<td valign="top"><screen>inherit.Shape@37d31475</screen><para>Desired:</para><screen><emphasis
role="red">(2.0|3.0)</emphasis></screen></td>
</tr>
</informaltable>
<figure xml:id="sda_inherit_fig_shapeToStringRedefine">
<title>Overwriting <methodname
xlink:href="javaapi://Object#toString--">toString()</methodname></title>
<imagedata fileref="Fig/shapeOverrideToStringIde.multi.svg"/>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sda_inherit_fig_shapeExtendObject">
<title><classname>Shape</classname> extending
<classname>Object</classname></title>
<mediaobject>
<imageobject>
<imagedata fileref="Fig/shapeRedefineToString.multi.svg"/>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sda_inherit_fig_RectangleLogging">
<title>Logging <classname>Rectangle</classname> instances</title>
<informaltable border="0">
<tr>
<th>Code</th>
<tr>
<td valign="top"><programlisting language="java">final Rectangle r = // Center coordinates,
new Rectangle(2.0, 3.0, 3.0, 4.0); // width and height
System.out.println(r);</programlisting></td>
<td valign="top"><screen>(2.0|3.0)</screen><para>Desired:</para><screen><emphasis
role="red">Rectangle at </emphasis>(2.0|3.0)<emphasis
role="red">, width= 3.0, height=4.0</emphasis></screen></td>
</tr>
</informaltable>
</figure>
<figure xml:id="sda_inherit_fig_RectangleOverrideToStringAgain">
<title>Override <methodname>toString()</methodname> in class
<classname>Rectangle</classname>.</title>
<programlisting language="java">public class Rectangle extends Shape {
@Override public String toString() {
return "<emphasis role="red">Rectangle at </emphasis>" + super.toString() <co
linkends="sda_inherit_fig_RectangleOverrideToStringAgain-1"
xml:id="sda_inherit_fig_RectangleOverrideToStringAgain-1-co"/> +
"<emphasis role="red">, width= </emphasis>" + <emphasis role="red">width</emphasis> + "<emphasis
role="red">, height=</emphasis>" + <emphasis role="red">height</emphasis>; <co
linkends="sda_inherit_fig_RectangleOverrideToStringAgain-2"
xml:id="sda_inherit_fig_RectangleOverrideToStringAgain-2-co"/>
} ...</programlisting>
<calloutlist>
<callout arearefs="sda_inherit_fig_RectangleOverrideToStringAgain-1-co"
xml:id="sda_inherit_fig_RectangleOverrideToStringAgain-1">
<para>The <code language="java"
xlink:href="https://docs.oracle.com/javase/tutorial/java/IandI/super.html">super</code>
keyword allows for calling the superclass
<classname>Shape</classname>'s <methodname>toString()</methodname>
method inserting the (2.0|3.0) center coordinate.</para>
</callout>
<callout arearefs="sda_inherit_fig_RectangleOverrideToStringAgain-2-co"
xml:id="sda_inherit_fig_RectangleOverrideToStringAgain-2">
<para>Append class <classname>Rectangle</classname>'s
<quote>own</quote> <code language="java">width</code> and <code
language="java">height</code> attribute values.</para>
</callout>
</calloutlist>
</figure>
<figure xml:id="sda_inherit_fig_rectangleExtendShapa">
<title><classname>Rectangle</classname> extending
<imagedata fileref="Fig/rectangleRedefineToString.multi.svg"/>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sda_inherit_fig_CircleComplete">
<title>Implementing
<classname>Circle</classname>.<methodname>toString()</methodname></title>
<programlisting language="java">public class Circle extends Shape {
/**
* Creating a circle of given center and radius
* @param x Center's x component.
* @param y Center's y component.
* @param radius The circle's radius.
*/
public Circle(double x,double y, double radius) {
super(x, y);
this.radius = radius;
}
@Override public String toString() {
return "Circle at " + super.toString() +", radius= " + radius;
}
private double radius;
}</programlisting>
</figure>
<figure xml:id="sda_inherit_fig_shapeToString">
<title><classname>Shape</classname> and
<methodname>toString()</methodname></title>
</imageobject>
</mediaobject>
</figure>
<qandaset defaultlabel="qanda"
xml:id="sd1_quanda_inherit_StringBufferNoEqualMethod">
<title><classname>String</classname> vs.
<classname>StringBuffer</classname></title>
<qandadiv>
<qandaentry>
<question>
<para>Consider two <classname
xlink:href="javaapi://StringBuffer">StringBuffer</classname>
instances:</para>
<informaltable border="1">
<colgroup width="54%"/>
<colgroup width="46%"/>
<tr>
<th>Code</th>
<th>Execution result</th>
</tr>
<tr>
<td valign="top"><programlisting language="java">final <link
xlink:href="javaapi://StringBuffer">StringBuffer</link>
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
a = new StringBuffer("test"),
b = new StringBuffer("test");
System.out.println(a.equals(b));</programlisting></td>
<td valign="top"><screen>false</screen></td>
</tr>
</informaltable>
<para>Strangely instances of String behave differently:</para>
<informaltable border="1">
<colgroup width="54%"/>
<colgroup width="46%"/>
<tr>
<th>Code</th>
<th>Execution result</th>
</tr>
<tr>
<td valign="top"><programlisting language="java">final String
a = new String("test"),
b = new String("test");
System.out.println(a.equals(b));</programlisting></td>
<td valign="top"><screen>true</screen></td>
</tr>
</informaltable>
<para>Explain this different behaviour.</para>
<tip>
<para>Take a closer look at the <classname
xlink:href="javaapi://String">String</classname> and <classname
xlink:href="javaapi://StringBuffer">StringBuffer</classname>
<xref linkend="glo_API"/> regarding the
<methodname>toString()</methodname> method.</para>
</tip>
</question>
<answer>
<para>The <classname
xlink:href="javaapi://String">String</classname> <xref
linkend="glo_API"/> reveals:</para>
<screen>public boolean equals (Object anObject)
Compares this string to the specified object. The result is true if and only if the argument is
not null and is a String object that represents the same sequence of characters as this object.
Overrides: equals in class Object
Parameters:
anObject - The object to compare this String against
Returns:
true if the given object represents a String equivalent to this string, false otherwise</screen>
<para>In a nutshell: Two instances of String will be compared for
equality character by character. The superclass <classname
xlink:href="javaapi://Object">Object</classname>.<methodname
xlink:href="javaapi://Object#equals(java.lang.Object)">equals()</methodname>
method is being overridden.</para>
<para>In class <classname
xlink:href="javaapi://StringBuffer">StringBuffer</classname> we do
not find any <methodname>equals()</methodname> method. Thus
xlink:href="javaapi://Object">Object</classname>.<methodname
xlink:href="javaapi://Object#equals(java.lang.Object)">equals()</methodname>
is not being overridden. When comparing two instances of
<classname
xlink:href="javaapi://StringBuffer">StringBuffer</classname>
xlink:href="javaapi://Object">Object</classname>.<methodname
xlink:href="javaapi://Object#equals(java.lang.Object)">equals()</methodname>
will be executed. Its <xref linkend="glo_API"/> reveals:</para>
<screen>public boolean equals (Object obj)
Indicates whether some other object is "equal to" this one.
...
Parameters:
obj - the reference object with which to compare.
Returns:
true <emphasis role="red">if this object is the same as the obj argument</emphasis>; false otherwise.</screen>
<para>Thus two instances of <classname
xlink:href="javaapi://StringBuffer">StringBuffer</classname> will
be compared for object identity rather than representing the same
string value.</para>
</answer>
</qandaentry>
</qandadiv>
</qandaset>
<qandaset defaultlabel="qanda"
xml:id="sd1_quanda_inheritDirectionAlternateImpl">
<title>Alternate implementation of opposite directions</title>
<qandadiv>
<qandaentry>
<question>
<para>Provide a different implementation of your <methodname
xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/ObjectsAndClasses/Enum/Compass_2.0/src/main/java/de/hdm_stuttgart/mi/sd1/direction/Direction.java#L28">opposite()</methodname>
from <xref linkend="sd1_qanda_enumDirectionNeighbours"/>. Follow
<uri
xlink:href="https://stackoverflow.com/questions/5678309/illegal-forward-reference-and-enums#answer-49409377">https://stackoverflow.com/questions/5678309/illegal-forward-reference-and-enums#answer-49409377</uri>.
Start by investigating both <methodname
xlink:href="http://www.java2s.com/Tutorial/Java/0040__Data-Type/Usingthebuiltinenumerationmethodsvalues.htm">values()</methodname>
and <methodname
xlink:href="javaapi://Enum#ordinal()">ordinal()</methodname>.</para>
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
</question>
<answer>
<para>We observe the following ordinal values:</para>
<informaltable border="0">
<tr>
<td valign="top"><programlisting language="java">public enum Direction {
N( 0, "north"), // 0
NE( 45, "north by east"), // 1
E( 90, "east"), // 2
SE(135, "south by east"), // 3
S( 180, "south"), // 4
SW(225, "south by west"), // 5
W( 270, "west"), // 6
NW(315, "north by west"); // 7
...</programlisting></td>
<td valign="top"><programlisting language="none">public Direction opposite() {
switch (this) {
case N: return S; // <emphasis role="red">0 --> 4</emphasis>
case NE: return SW; // <emphasis role="red">1 --> 5</emphasis>
case E: return W; // <emphasis role="red">2 --> 6</emphasis>
case SE: return NW; // <emphasis role="red">3 --> 7</emphasis>
case S: return N; // <emphasis role="red">4 --> 0</emphasis>
case SW: return NE; // <emphasis role="red">5 --> 1</emphasis>
case W: return E; // <emphasis role="red">6 --> 2</emphasis>
case NW: return SE; // <emphasis role="red">7 --> 3</emphasis>
...</programlisting></td>
</tr>
</informaltable>
<para>We are thus left implementing an integer shift <code>(0, 1,
2, 3, 4, 5, 6, 7)</code> to <code>(4, 5, 6, 7, 0, 1, 2,
3)</code>:</para>
<programlisting language="java">public Direction <link
xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/ObjectsAndClasses/Enum/Compass_3.0/src/main/java/de/hdm_stuttgart/mi/sd1/direction/Direction.java#L28">opposite()</link> {
return values()[ (ordinal() + 4) % 8];
}</programlisting>
</answer>
</qandaentry>
</qandadiv>
</qandaset>
</section>
<section xml:id="sd1_inherit_sect_final">
<title><code language="java">final</code> methods</title>
<figure xml:id="sda_inherit_fig_moveRectangle">
<title>Moving <classname>Shape</classname> instances</title>
<mediaobject>
<imageobject>
<imagedata fileref="Fig/rectangleTranslate.multi.svg"/>
</imageobject>
</mediaobject>
</figure>
<figure xml:id="sda_inherit_fig_shapeMove">
<title>Implementing <classname>Shape</classname> movements</title>
<programlisting language="java">public class Shape {
/**
* Move by a given translation vector
* @param xTrans Translation's x component
* @param yTrans Translation's y component
*/
public void move(final int xTrans, final int yTrans) {
x += xTrans;
y += yTrans;
} ...</programlisting>
</figure>
<figure xml:id="sda_inherit_fig_shapeMoveProblemSubclass">
<title>Fools are everywhere!</title>
<programlisting language="java">public class Rectangle extends Shape {
@Override public void move(int xTrans, int yTrans) {
// I'm so dumb!
<figure xml:id="sda_inherit_fig_shapeMoveProblemSubclassSolution">
<title>Solution: <emphasis role="red">final</emphasis> prevents
overriding</title>
<programlisting language="none">public abstract class Shape {
... public <emphasis role="red">final</emphasis> void move(final int xTrans, final int yTrans) {
x += xTrans;
y += yTrans;
}...</programlisting>
<programlisting language="java">public class Rectangle extends Shape {
// Syntax error: 'move(int, int)' cannot override
// 'move(int, int)' in 'inherit.Shape'; overridden method is final
@Override public void move(int xTrans, int yTrans) {...</programlisting>
</figure>
</section>
<section xml:id="sd1_inherit_sect_abstractMethods">
<title>Abstract methods</title>
<figure xml:id="sda_inherit_fig_subclassImplementGetArea">
<title>Calculating a shape's area</title>
<informaltable border="0">
<tr>
<td valign="top"><programlisting language="java">public class Rectangle extents Shape {
*/
public double getArea() {
return width * height;
<td valign="top"><programlisting language="java">public class Circle extents Shape {
/**
* Calculate the area.
* @return The circle's area
*/
public double getArea() {
return PI * radius * radius;
} ...</programlisting></td>
</tr>
</informaltable>
</figure>
<figure xml:id="sda_inherit_fig_shapePolymorphicAreaCall">
<title>Desired: Polymorphic <methodname>getArea()</methodname>