Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
GoikLectures
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Goik Martin
GoikLectures
Commits
0a199b4f
Commit
0a199b4f
authored
7 years ago
by
Goik Martin
Browse files
Options
Downloads
Patches
Plain Diff
refining equals()
parent
c8080b7d
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
Doc/Sd1/inheritance.xml
+191
-67
191 additions, 67 deletions
Doc/Sd1/inheritance.xml
with
191 additions
and
67 deletions
Doc/Sd1/inheritance.xml
+
191
−
67
View file @
0a199b4f
...
...
@@ -29,8 +29,9 @@
}
</programlisting></td>
<td
valign=
"top"
><programlisting
language=
"none"
>
public class Circle {
// Center coordinate
<coref
linkend=
"sda_inherit_fig_codeDuplicate-1-co"
/>
private
<emphasis
role=
"red"
>
double x
</emphasis>
;
// Center coordinate
private
<emphasis
role=
"red"
>
double x
</emphasis>
;
<coref
linkend=
"sda_inherit_fig_codeDuplicate-1-co"
/>
private
<emphasis
role=
"red"
>
double y
</emphasis>
;
private double radius;
<co
linkends=
"sda_inherit_fig_codeDuplicate-3"
...
...
@@ -437,15 +438,24 @@ public Rectangle(double x, double y,
<programlisting
language=
"java"
>
public class Rectangle extends Shape {
@Override public void move(int xTrans, int yTrans) {
// I'm so dumb!
...
}
</programlisting>
</figure>
<para>
Solution: Prohibit overriding
<methodname>
move()
</methodname>
in
superclass
<code
language=
"java"
>
Shape
</code>
:
</para>
<figure
xml:id=
"sda_inherit_fig_shapeMoveProblemSubclassSolution"
>
<title>
Solution:
<emphasis
role=
"red"
>
final
</emphasis>
prevents
overriding
</title>
<programlisting
language=
"none"
>
... public
<emphasis
role=
"red"
>
final
</emphasis>
void move(final int xTrans, final int yTrans) {
x += xTrans;
y += yTrans;
} ...
</programlisting>
<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>
...
...
@@ -457,20 +467,20 @@ public Rectangle(double x, double y,
<informaltable
border=
"0"
>
<tr>
<td
valign=
"top"
><programlisting
language=
"java"
>
/**
<td
valign=
"top"
><programlisting
language=
"java"
>
public class Rectangle extents Shape {
/**
* Calculate the area.
* @return The rectangle's area
*/
@Override
public double getArea() {
return width * height;
}
</programlisting></td>
<td
valign=
"top"
><programlisting
language=
"java"
>
/**
<td
valign=
"top"
><programlisting
language=
"java"
>
public class Circle extents Shape {
/**
* Calculate the area.
* @return The circle's area
*/
@Override
public double getArea() {
return Math.PI * radius * radius;
}
</programlisting></td>
...
...
@@ -479,19 +489,22 @@ public Rectangle(double x, double y,
</figure>
<figure
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall"
>
<title>
Want
ed: Polymorphic
<methodname>
getArea()
</methodname>
<title>
Desir
ed: Polymorphic
<methodname>
getArea()
</methodname>
call
</title>
<programlisting
language=
"none"
>
final Shape[] shapes
<co
linkends=
"sda_inherit_fig_shapePolymorphicAreaCall-1"
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall-1-co"
/>
= {new Circle(1, 1, 2.)
<co
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall-1-co"
/>
= {
new Circle(1, 1, 2.)
<co
linkends=
"sda_inherit_fig_shapePolymorphicAreaCall-2"
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall-2-co"
/>
,
new Rectangle(1, -1, 2., 3.)
<coref
new Rectangle(1, -1, 2., 3.)
<coref
linkend=
"sda_inherit_fig_shapePolymorphicAreaCall-2-co"
/>
};
for (final Shape s : shapes) {
System.out.println(s.toString() + ":
<emphasis
role=
"red"
>
area = " + s.getArea()
</emphasis>
);
System.out.println(s.toString() + ":
<emphasis
role=
"red"
>
area = " + s.getArea()
</emphasis>
);
<co
linkends=
"sda_inherit_fig_shapePolymorphicAreaCall-3"
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall-3-co"
/>
}
</programlisting>
<screen>
Circle at (1.0|1.0), radius= 2.0:
<emphasis
role=
"red"
>
area = 12.566370614359172
</emphasis>
...
...
@@ -511,28 +524,34 @@ Rectangle at (1.0|-1.0), width= 2.0, height=3.0: <emphasis role="red">area = 6.0
<classname>
Circle
</classname>
. We can thus assign both
<classname>
Circle
</classname>
and
<classname>
Rectangle
</classname>
instances to variables (or array elements) of type
<classname>
Shape
</classname>
by upcasting.
</para>
<classname>
Shape
</classname>
by means of upcasting.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_shapePolymorphicAreaCall-3-co"
xml:id=
"sda_inherit_fig_shapePolymorphicAreaCall-3"
>
<para>
Polymorphic dispatch: Depending on the object's type the
<xref
linkend=
"glo_Java"
/>
runtime will automatically choose either
<classname>
Rectangle
</classname>
.
<methodname>
toString()
</methodname>
/
<classname>
Rectangle
</classname>
.
<methodname>
getArea()
</methodname>
or
<classname>
Circle
</classname>
.
<methodname>
getArea()
</methodname>
/
<classname>
Circle
</classname>
.
<methodname>
toString()
</methodname>
/
<classname>
Circle
</classname>
.
<methodname>
getArea()
</methodname>
respectively.
</para>
</callout>
</calloutlist>
<figure
xml:id=
"sda_inherit_fig_getAreaPolymorphicProblem"
>
<title>
Problem
</title>
<title>
Problem
s:
</title>
<itemizedlist>
<listitem>
<para>
No
such
<methodname>
getArea()
</methodname>
method in
class
<classname>
Shape
</classname>
.
</para>
<para>
No
meaningful
<methodname>
getArea()
</methodname>
method in
class
<classname>
Shape
</classname>
possible
.
</para>
</listitem>
<listitem>
<para>
No meaningful implementation in
<classname>
Shape
</classname>
.
</para>
</listitem>
<listitem>
<para>
Meaningful implementations in both subclasses
<classname>
Rectangle
</classname>
and
<classname>
Circle
</classname>
.
</para>
<para>
Meaningful implementations exist both in subclass
<classname>
Rectangle
</classname>
and
<classname>
Circle
</classname>
.
</para>
</listitem>
</itemizedlist>
...
...
@@ -595,20 +614,27 @@ Rectangle at (1.0|-1.0), width= 2.0, height=3.0: <emphasis role="red">area = 6.0
<para>
Superclass
<classname>
Shape
</classname>
contains an
<code
language=
"java"
>
abstract
</code>
method and must thus itself be
declared
<code
language=
"java"
>
abstract
</code>
as well.
</para>
<note>
<para>
You cannot create instances of
<code
language=
"java"
>
abstract
</code>
classes. You may however create
instances of derived non-
<code
language=
"java"
>
abstract
</code>
classes.
</para>
</note>
</callout>
<callout
arearefs=
"sda_inherit_fig_implementAbstractGetArea-2-co"
xml:id=
"sda_inherit_fig_implementAbstractGetArea-2"
>
<para>
Method
<classname>
getArea()
</classname>
cannot be implemented in
a meaningful way. Its
<code
language=
"java"
>
abstract
</code>
modifier
is a promise that
any
concrete (= non-
<code
is a promise that
some
concrete (= non-
<code
language=
"java"
>
abstract
</code>
) subclass will either offer an
implementation of
<classname>
getArea()
</classname>
or will have a
parent class doing so.
</para>
implementation of
<classname>
getArea()
</classname>
or will have a
n
intermediate
parent class doing so.
</para>
<para>
The
<code
language=
"java"
>
abstract
</code>
keyword requires a
corresponding implementation in
any
derived
non-
<code
language=
"java"
>
abstract
</code>
subclass.
</para>
<para>
In other words:
The
<code
language=
"java"
>
abstract
</code>
keyword requires a
corresponding implementation in
some
derived
non-
<code
language=
"java"
>
abstract
</code>
subclass.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_implementAbstractGetArea-3-co"
...
...
@@ -923,7 +949,8 @@ public abstract class Shape <co
final protected long
<emphasis
role=
"red"
>
creationTime
</emphasis>
<co
linkends=
"sda_inherit_fig_protectedCreationTime-2"
xml:id=
"sda_inherit_fig_protectedCreationTime-2-co"
/>
= System.nanoTime();
... }
...
}
------------------------------------------------
<emphasis
role=
"red"
>
package model.sub
</emphasis>
;
public class Rectangle
<co
linkends=
"sda_inherit_fig_protectedCreationTime-3"
...
...
@@ -935,36 +962,37 @@ public class Rectangle <co linkends="sda_inherit_fig_protectedCreationTime-3"
linkends=
"sda_inherit_fig_protectedCreationTime-4"
xml:id=
"sda_inherit_fig_protectedCreationTime-4-co"
/>
);
return width * height;
} ... }
</programlisting>
} ...
}
</programlisting>
</figure>
<calloutlist>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-1-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-1"
>
<para>
Defining superclass
<classname>
Shape
</classname>
in package
<code
language=
"java"
>
model
</code>
.
</para>
</callout>
<calloutlist>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-1-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-1"
>
<para>
Defining superclass
<classname>
Shape
</classname>
in package
<code
language=
"java"
>
model
</code>
.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-2-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-2"
>
<para>
Defining a
<code
language=
"java"
>
protected
</code>
instance
attribute
<property>
creationTime
</property>
in superclass
<classname>
Shape
</classname>
.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-2-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-2"
>
<para>
Defining a
<code
language=
"java"
>
protected
</code>
instance
attribute
<property>
creationTime
</property>
in superclass
<classname>
Shape
</classname>
.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-3-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-3"
>
<para>
Deriving class
<classname>
Rectangle
</classname>
in different
package
<code
language=
"java"
>
model.sub
</code>
from superclass
<code
language=
"java"
>
Shape
</code>
.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-3-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-3"
>
<para>
Deriving class
<classname>
Rectangle
</classname>
in different
package
<code
language=
"java"
>
model.sub
</code>
from superclass
<code
language=
"java"
>
Shape
</code>
.
</para>
</callout>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-4-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-4"
>
<para>
Accessing superclass attribute
<property>
creationTime
</property>
across package boundary.
</para>
</callout>
</calloutlist>
</figure>
<callout
arearefs=
"sda_inherit_fig_protectedCreationTime-4-co"
xml:id=
"sda_inherit_fig_protectedCreationTime-4"
>
<para>
Accessing superclass attribute
<property>
creationTime
</property>
across package boundary.
</para>
</callout>
</calloutlist>
<qandaset
defaultlabel=
"qanda"
xml:id=
"sd1_qanda_protectedPackagePrivate"
>
<title><code
language=
"java"
>
protected
</code>
vs.
<quote>
package
...
...
@@ -1159,14 +1187,15 @@ public class Rectangle
<tr>
<td
valign=
"top"
><programlisting
language=
"java"
>
public static void main(String[] args) {
final Shape[] shapes = {new Circle(1, 1, 2.),
final Shape[] shapes = {
new Circle(1, 1, 2.),
new Rectangle(1, -1, 2., 3.)};
print(shapes);
}
static void print(final Shape[] shapes) {
for (final Shape s : shapes) {
if (s instanceof Rectangle) {
System.out.println("Type Rectangle");
System.out.println("Type Rectangle");
} else if (s instanceof Circle) {
System.out.println("Type Circle");
}
...
...
@@ -1179,6 +1208,57 @@ Type Rectangle</screen></td>
</informaltable>
</figure>
<figure
xml:id=
"sd1_inherit_fig_shapeDefineEquals"
>
<title>
Defining
<methodname>
equals(...)
</methodname>
of
<classname>
Shape
</classname>
instances
</title>
<para>
Two
<classname>
Shape
</classname>
instances shall be considered
equal if:
</para>
<itemizedlist>
<listitem>
<para>
Both instances are of common type
<abbrev>
i.e.
</abbrev>
either
<classname>
Rectangle
</classname>
or
<classname>
Circle
</classname>
.
</para>
</listitem>
<listitem>
<para>
Their center coordinates match within a threshold of
<inlineequation>
<m:math
display=
"inline"
>
<m:msup>
<m:mi>
10
</m:mi>
<m:mrow>
<m:mo>
-
</m:mo>
<m:mi>
15
</m:mi>
</m:mrow>
</m:msup>
</m:math>
</inlineequation>
.
</para>
</listitem>
<listitem>
<para><code
language=
"java"
>
width
</code>
and
<code
language=
"java"
>
height
</code>
or
<code
language=
"java"
>
radius
</code>
match within a threshold of
<inlineequation>
<m:math
display=
"inline"
>
<m:msup>
<m:mi>
10
</m:mi>
<m:mrow>
<m:mo>
-
</m:mo>
<m:mi>
15
</m:mi>
</m:mrow>
</m:msup>
</m:math>
</inlineequation>
.
</para>
</listitem>
</itemizedlist>
</figure>
<figure
xml:id=
"sd1_inherit_fig_equalByCoordinate"
>
<title>
Comparing center coordinates
</title>
...
...
@@ -1191,6 +1271,27 @@ Type Rectangle</screen></td>
...
</programlisting>
</figure>
<figure
xml:id=
"sd1_inherit_fig_rectangleEquals"
>
<title>
Implementing
<classname>
Rectangle
</classname>
.
<methodname
xlink:href=
"https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#equals-java.lang.Object-"
>
equals()
</methodname></title>
<programlisting
language=
"java"
>
public class Rectangle extends Shape {
@Override public boolean equals(Object o) {
if (o instanceof Rectangle){
final Rectangle oRectangle = (Rectangle) o;
return super.equalCenter(oRectangle)
&&
Math.abs(oRectangle.width- width) +
Math.abs(oRectangle.height- height)
<
1.E-15;
}
return false;
}
...
</programlisting>
<remark>
if
<code
language=
"java"
>
o == null
</code>
the expression
<code
language=
"java"
>
o instanceof Rectangle
</code>
evaluates to
<code
language=
"java"
>
false
</code>
.
</remark>
</figure>
<figure
xml:id=
"sd1_inherit_fig_circleEquals"
>
<title>
Implementing
<classname>
Circle
</classname>
.
<methodname
xlink:href=
"https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#equals-java.lang.Object-"
>
equals()
</methodname></title>
...
...
@@ -1200,14 +1301,37 @@ Type Rectangle</screen></td>
if (o instanceof Circle){
final Circle oCircle = (Circle) o;
return super.equalCenter(o)
&&
Math.abs(oCircle.radius - radius)
<
1.E-15;
Math.abs(oCircle.radius - radius)
<
1.E-15;
}
return false;
} ...
</programlisting>
</figure>
<remark>
if
<code
language=
"java"
>
o == null
</code>
the expression
<code
language=
"java"
>
o instanceof Circle
</code>
evaluates to
<code
language=
"java"
>
false
</code>
.
</remark>
<figure
xml:id=
"sd1_inherit_fig_testShapeEquals"
>
<title>
Testing equality of
<classname>
Shape
</classname>
objects
</title>
<informaltable
border=
"0"
>
<colgroup
width=
"72%"
/>
<colgroup
width=
"28%"
/>
<tr>
<td
valign=
"top"
><programlisting
language=
"java"
>
final Rectangle
r1 = new Rectangle(2, 3, 1,4),
r2 = new Rectangle(2, 3, 2,8),
r3 = new Rectangle(2, 3, 1,4);
final Circle c = new Circle(2,3, 7);
System.out.println("r1.equals(r2): " + r1.equals(r2));
System.out.println("r1.equals(r3): " + r1.equals(r3));
System.out.println("c.equals(r1): " + c.equals(r1));
</programlisting></td>
<td
valign=
"top"
><screen>
r1.equals(r2): false
r1.equals(r3): true
c.equals(r1): false
</screen></td>
</tr>
</informaltable>
</figure>
</section>
</chapter>
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment