0% found this document useful (0 votes)
19 views14 pages

OOP2024 JavaExercises Lab6 OOP-Inheritance

Uploaded by

24002067
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views14 pages

OOP2024 JavaExercises Lab6 OOP-Inheritance

Uploaded by

24002067
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

HaQT Object-Oriented Programming

Lab 6. OOP - Inheritance

Writing Good Programs


The only way to learn programming is program, program and program. Learning
programming is like learning cycling, swimming or any other sports. You can’t learn
by watching or reading books. Start to program immediately. On the other hands, to
improve your programming, you need to read many books and study how the masters
program.
It is easy to write programs that work. It is much harder to write programs that not
only work but also easy to maintain and understood by others – I call these good
programs. In the real world, writing program is not meaningful. You have to write
good programs, so that others can understand and maintain your programs.
Pay particular attention to:

1. Coding style:

• Read Java code convention: ”Google Java Style Guide” or ”Java Code
Conventions - Oracle”.
• Follow the Java Naming Conventions for variables, methods, and classes
STRICTLY. Use CamelCase for names. Variable and method names begin
with lowercase, while class names begin with uppercase. Use nouns for
variables (e.g., radius) and class names (e.g., Circle). Use verbs for methods
(e.g., getArea(), isEmpty()).
• Use Meaningful Names: Do not use names like a, b, c, d, x, x1, x2,
and x1688 - they are meaningless. Avoid single-alphabet names like i, j, k.
They are easy to type, but usually meaningless. Use single-alphabet names
only when their meaning is clear, e.g., x, y, z for co-ordinates and i for array
index. Use meaningful names like row and col (instead of x and y, i and j,
x1 and x2), numStudents (not n), maxGrade, size (not n), and upperbound
(not n again). Differentiate between singular and plural nouns (e.g., use
books for an array of books, and book for each item).
• Use consistent indentation and coding style. Many IDEs (such as Eclipse /
NetBeans) can re-format your source codes with a single click.

2. Program Documentation: Comment! Comment! and more Comment to


explain your code to other people and to yourself three days later.

3. The problems in this tutorial are certainly NOT challenging. There are tens
of thousands of challenging problems available – used in training for various
programming contests (such as International Collegiate Programming Contest
(ICPC), International Olympiad in Informatics (IOI)).

1
HaQT Object-Oriented Programming

1 Exercises on Inheritance

1.1 An Introduction to OOP Inheritance by Example - The Circle


and Cylinder Classes

This exercise shall guide you through the important concepts in inheritance.

In this exercise, a subclass called Cylinder is derived from the superclass Circle as shown
in the class diagram (where an an arrow pointing up from the subclass to its superclass).
Study how the subclass Cylinder invokes the superclass’ constructors (via super() and su-
per(radius)) and inherits the variables and methods from the superclass Circle.

You can reuse the Circle class that you have created in the previous exercise. Make sure
that you keep ”Circle.class” in the same directory.

1 p u b l i c c l a s s C y l i n d e r e x t e n d s C i r c l e { // Save a s ” C y l i n d e r . j a v a ”
p r i v a t e d o u b l e h e i g h t ; // p r i v a t e v a r i a b l e
3

2
HaQT Object-Oriented Programming

// C o n s t r u c t o r with d e f a u l t c o l o r , r a d i u s and h e i g h t
5 public Cylinder () {
super () ; // c a l l s u p e r c l a s s no−a r g c o n s t r u c t o r C i r c l e ( )
7 height = 1 . 0 ;
}
9 // C o n s t r u c t o r with d e f a u l t r a d i u s , c o l o r but g i v e n h e i g h t
p u b l i c Cylinder ( double height ) {
11 super () ; // c a l l s u p e r c l a s s no−a r g c o n s t r u c t o r C i r c l e ( )
this . height = height ;
13 }
// C o n s t r u c t o r with d e f a u l t c o l o r , but g i v e n r a d i u s , h e i g h t
15 p u b l i c Cylinder ( double radius , double height ) {
s u p e r ( r a d i u s ) ; // c a l l s u p e r c l a s s c o n s t r u c t o r C i r c l e ( r )
17 this . height = height ;
}
19
// A p u b l i c method f o r r e t r i e v i n g t h e h e i g h t
21 p u b l i c double getHeight ( ) {
return height ;
23 }

25 // A p u b l i c method f o r computing t h e volume o f c y l i n d e r


// u s e s u p e r c l a s s method getArea ( ) t o g e t t h e b a s e a r e a
27 p u b l i c d o u b l e getVolume ( ) {
r e t u r n getArea ( ) ∗ h e i g h t ;
29 }
}

Write a test program (says TestCylinder) to test the Cylinder class created, as follow:

p u b l i c c l a s s T e s t C y l i n d e r { // s a v e a s ” T e s t C y l i n d e r . j a v a ”
2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
// D e c l a r e and a l l o c a t e a new i n s t a n c e o f c y l i n d e r
4 // with d e f a u l t c o l o r , r a d i u s , and h e i g h t
C y l i n d e r c y l i n d e r 1 = new C y l i n d e r ( ) ;
6 System . out . p r i n t l n ( ” C y l i n d e r : ”
+ ” r a d i u s=” + c y l i n d e r 1 . g e t R a d i u s ( )
8 + ” h e i g h t=” + c y l i n d e r 1 . g e t H e i g h t ( )
+ ” b a s e a r e a=” + c y l i n d e r 1 . getArea ( )
10 + ” volume=” + c y l i n d e r 1 . getVolume ( ) ) ;

12 // D e c l a r e and a l l o c a t e a new i n s t a n c e o f c y l i n d e r
// s p e c i f y i n g h e i g h t , with d e f a u l t c o l o r and r a d i u s
14 C y l i n d e r c y l i n d e r 2 = new C y l i n d e r ( 1 0 . 0 ) ;
System . out . p r i n t l n ( ” C y l i n d e r : ”
16 + ” r a d i u s=” + c y l i n d e r 2 . g e t R a d i u s ( )
+ ” h e i g h t=” + c y l i n d e r 2 . g e t H e i g h t ( )

3
HaQT Object-Oriented Programming

18 + ” b a s e a r e a=” + c y l i n d e r 2 . getArea ( )
+ ” volume=” + c y l i n d e r 2 . getVolume ( ) ) ;
20
// D e c l a r e and a l l o c a t e a new i n s t a n c e o f c y l i n d e r
22 // s p e c i f y i n g r a d i u s and h e i g h t , with d e f a u l t c o l o r
C y l i n d e r c y l i n d e r 3 = new C y l i n d e r ( 2 . 0 , 1 0 . 0 ) ;
24 System . out . p r i n t l n ( ” C y l i n d e r : ”
+ ” r a d i u s=” + c y l i n d e r 3 . g e t R a d i u s ( )
26 + ” h e i g h t=” + c y l i n d e r 3 . g e t H e i g h t ( )
+ ” b a s e a r e a=” + c y l i n d e r 3 . getArea ( )
28 + ” volume=” + c y l i n d e r 3 . getVolume ( ) ) ;
}
30 }

Method Overriding and ”Super”: The subclass Cylinder inherits getArea() method
from its superclass Circle. Try overriding the getArea() method in the subclass Cylinder to
compute the surface area (= 2π ×radius×height+2×base−area) of the cylinder instead of
base area. That is, if getArea() is called by a Circle instance, it returns the area. If getArea()
is called by a Cylinder instance, it returns the surface area of the cylinder.

If you override the getArea() in the subclass Cylinder, the getVolume() no longer works. This
is because the getVolume() uses the overridden getArea() method found in the same class.
(Java runtime will search the superclass only if it cannot locate the method in this class).
Fix the getVolume().

Hints

After overridding the getArea() in subclass Cylinder, you can choose to invoke the getArea()
of the superclass Circle by calling super.getArea().

Try

Provide a toString() method to the Cylinder class, which overrides the toString() inherited
from the superclass Circle, e.g.,

@Override
2 public String toString () { // i n C y l i n d e r c l a s s
return ” Cylinder : s u b c l a s s of ” + super . toString () // u s e C i r c l e ’ s
,→ t o S t r i n g ( )
4 + ” h e i g h t=” + h e i g h t ;
}

4
HaQT Object-Oriented Programming

Try out the toString() method in TestCylinder.

Note

@Override is known as annotation (introduced in JDK 1.5), which asks compiler to check
whether there is such a method in the superclass to be overridden. This helps greatly if you
misspell the name of the toString(). If @Override is not used and toString() is misspelled
as ToString(), it will be treated as a new method in the subclass, instead of overriding the
superclass. If @Override is used, the compiler will signal an error. @Override annotation is
optional, but certainly nice to have.

1.2 Superclass Person and its subclasses

Write the classes as shown in the following class diagram. Mark all the overridden methods
with annotation @Override.

5
HaQT Object-Oriented Programming

1.3 Point2D and Point3D

Write the classes as shown in the following class diagram. Mark all the overridden methods
with annotation @Override.

Hints

1. You cannot assign floating-point literal say 1.1 (which is a double) to a f loat variable,
you need to add a suffix f, e.g. 0.0f , 1.1f .

2. The instance variables x and y are private in Point and cannot be accessed directly in
the subclass MovablePoint. You need to access via the public getters and setters. For
example, you cannot write x += xSpeed, you need to write setX(getX() + xSpeed).

1.4 Superclass Shape and its subclasses Circle, Rectangle and


Square

6
HaQT Object-Oriented Programming

Write a superclass called Shape (as shown in the class diagram), which contains:

• Two instance variables color (String) and filled (boolean).


• Two constructors: a no-arg (no-argument) constructor that initializes the color to
”green” and filled to true, and a constructor that initializes the color and filled to the

7
HaQT Object-Oriented Programming

given values.

• Getter and setter for all the instance variables. By convention, the getter for a boolean
variable xxx is called isXXX() (instead of getXxx() for all the other types).

• A toString() method that returns ”A Shape with color of xxx and filled/Not filled”.

Write a test program to test all the methods defined in Shape.

Write two subclasses of Shape called Circle and Rectangle, as shown in the class diagram.

The Circle class contains:

• An instance variable radius (double).

• Three constructors as shown. The no-arg constructor initializes the radius to 1.0.

• Getter and setter for the instance variable radius.

• Methods getArea() and getPerimeter().

• Override the toString() method inherited, to return ”A Circle with radius = xxx,
which is a subclass of yyy”, where yyy is the output of the toString() method from the
superclass.

The Rectangle class contains:

• Two instance variables width (double) and length (double).

• Three constructors as shown. The no-arg constructor initializes the width and length
to 1.0.

• Getter and setter for all the instance variables.

• Methods getArea() and getPerimeter().

• Override the toString() method inherited, to return ”A Rectangle with width = xxx
and length = zzz, which is a subclass of yyy”, where yyy is the output of the toString()
method from the superclass.

Write a class called Square, as a subclass of Rectangle. Convince yourself that Square can
be modeled as a subclass of Rectangle. Square has no instance variable, but inherits the
instance variables width and length from its superclass Rectangle.

• Provide the appropriate constructors (as shown in the class diagram).

8
HaQT Object-Oriented Programming

Hint:

1 p u b l i c Square ( d o u b l e s i d e ) {
s u p e r ( s i d e , s i d e ) ; // C a l l s u p e r c l a s s R e c t a n g l e ( double , d o u b l e )
3 }

• Override the toString() method to return ”A Square with side = xxx, which is a
subclass of yyy”, where yyy is the output of the toString() method from the superclass.

• Do you need to override the getArea() and getPerimeter()? Try them out.

• Override the setLength() and setWidth() to change both the width and length, so as
to maintain the square geometry.

1.5 Superclass Animal and its subclasses

Write the codes for all the classes as shown in the class diagram.

9
HaQT Object-Oriented Programming

2 Exercises on Composition vs Inheritance

They are two ways to reuse a class in your applications: composition and inheritance.

2.1 The Point and Line Classes

Let us begin with composition with the statement ”a line composes of two points”.

Complete the definition of the following two classes: Point and Line. The class Line composes
2 instances of class Point, representing the beginning and ending points of the line. Also
write test classes for Point and Line (says TestPoint and TestLine).

/∗ ∗
2 ∗ P oi nt . j a v a
∗/
4 p u b l i c c l a s s Po in t {
// P r i v a t e v a r i a b l e s
6 private int x ; // x co−o r d i n a t e
private int y ; // y co−o r d i n a t e
8

// C o n s t r u c t o r
10 p u b l i c Po in t ( i n t x , i n t y ) { . . . . . . }

12 // P u b l i c methods
public String toString () {
14 r e t u r n ” P oi nt : ( ” + x + ” , ” + y + ” ) ” ;
}
16
public i n t getX ( ) { . . . . . . }
18 public i n t getY ( ) { . . . . . . }
public v o i d setX ( i n t x ) { . . . . . . }
20 public v o i d setY ( i n t y ) { . . . . . . }
public v o i d setXY ( i n t x , i n t y ) { . . . . . . }
22 }

/∗ ∗
2 ∗ TestPoint . java
∗/
4 public c l a s s TestPoint {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
6 Po i nt p1 = new Point ( 1 0 , 2 0 ) ; // C o n s t r u c t a Po in t
System . out . p r i n t l n ( p1 ) ;
8 // Try s e t t i n g p1 t o ( 1 0 0 , 1 0 ) .

10
HaQT Object-Oriented Programming

......
10 }
}

1 /∗ ∗
∗ Li ne . j a v a
3 ∗/
p u b l i c c l a s s L ine {
5 // A l i n e composes o f two p o i n t s ( a s i n s t a n c e v a r i a b l e s )
p r i v a t e P oint b e g i n ; // b e g i n n i n g p o i n t
7 p r i v a t e P oint end ; // e n d i n g p o i n t

9 // C o n s t r u c t o r s
p u b l i c L in e ( Po in t begin , Po in t end ) { // caller to construct the Points
11 t h i s . begin = begin ;
......
13 }
p u b l i c L ine ( i n t beginX , i n t beginY , i n t endX , i n t endY ) {
15 b e g i n = new P oi nt ( beginX , beginY ) ; // c o n s t r u c t t h e P o i n t s h e r e
......
17 }

19 // P u b l i c methods
public String toString () { . . . . . . }
21
public P oint g e t B e g i n ( ) { . . . . . . }
23 public P o in t getEnd ( ) { . . . . . . }
public void setBegin ( . . . . . . ) { . . . . . . }
25 public v o i d setEnd ( . . . . . . ) { . . . . . . }

27 public int getBeginX ( ) { ...... }


public int getBeginY ( ) { ...... }
29 public int getEndX ( ) { ...... }
public int getEndY ( ) { ...... }
31
public void setBeginX ( . . . . . . ) { . . . . . . }
33 public void setBeginY ( . . . . . . ) { . . . . . . }
public void setBeginXY ( . . . . . . ) { . . . . . . }
35 public void setEndX ( . . . . . . ) { . . . . . . }
public void setEndY ( . . . . . . ) { . . . . . . }
37 public void setEndXY ( . . . . . . ) { . . . . . . }

39 p u b l i c i n t g et Le ng th ( ) { . . . . . . } // Length o f t h e l i n e
// Math . s q r t ( x D i f f ∗ x D i f f + y D i f f ∗ y D i f f )
41 p u b l i c d o u b l e g e t G r a d i e n t ( ) { . . . . . . } // G r a d i e n t i n r a d i a n s
// Math . atan2 ( y D i f f , x D i f f )
43 }

11
HaQT Object-Oriented Programming

1 /∗ ∗
∗ TestLine . java
3 ∗/
public c l a s s TestLine {
5 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
Li ne l 1 = new Line ( 0 , 0 , 3 , 4 ) ;
7 System . out . p r i n t l n ( l 1 ) ;

9 P oi nt p1 = new Po in t ( . . . ) ;
P oi nt p2 = new Po in t ( . . . ) ;
11 Li ne l 2 = new Line ( p1 , p2 ) ;
System . out . p r i n t l n ( l 2 ) ;
13 ...
}
15 }

The class diagram for composition is as follows (where a diamond-hollow-head arrow pointing
to its constituents):

Instead of composition, we can design a Line class using inheritance. Instead of ”a line
composes of two points”, we can say that ”a line is a point extended by another point”, as
shown in the following class diagram:

Let’s re-design the Line class (called LineSub) as a subclass of class Point. LineSub inherits
the starting point from its superclass Point, and adds an ending point. Complete the class
definition. Write a testing class called TestLineSub to test LineSub.

12
HaQT Object-Oriented Programming

1 /∗ ∗
∗ LineSub . j a v a
3 ∗/
p u b l i c c l a s s LineSub e x t e n d s Po i nt {
5 // A l i n e n e e d s two p o i n t s : b e g i n and end .
// The b e g i n p o i n t i s i n h e r i t e d from i t s s u p e r c l a s s P oi nt .
7 // P r i v a t e v a r i a b l e s
Po i nt end ; // Ending p o i n t
9
// C o n s t r u c t o r s
11 p u b l i c LineSub ( i n t beginX , i n t beginY , i n t endX , i n t endY ) {
s u p e r ( beginX , beginY ) ; // c o n s t r u c t t h e b e g i n P oi nt
13 t h i s . end = new Po in t ( endX , endY ) ; // c o n s t r u c t t h e end P oi nt
}
15 p u b l i c LineSub ( P oint begin , P oi nt end ) { // caller to construct the Points
s u p e r ( b e g i n . getX ( ) , b e g i n . getY ( ) ) ; // need to reconstruct the begin Point
17 t h i s . end = end ;
}
19
// P u b l i c methods
21 // I n h e r i t s methods getX ( ) and getY ( ) from s u p e r c l a s s Po i nt
public String toString () { . . . }
23

public Po in t g e t B e g i n ( ) { . . . }
25 public P o in t getEnd ( ) { . . . }
public void setBegin ( . . . ) { . . . }
27 public v o i d setEnd ( . . . ) { . . . }

29 public int getBeginX ( ) { ... }


public int getBeginY ( ) { ... }
31 public int getEndX ( ) { ... }
public int getEndY ( ) { ... }
33
public void setBeginX ( . . . ) { . . . }
35 public void setBeginY ( . . . ) { . . . }
public void setBeginXY ( . . . ) { . . . }
37 public void setEndX ( . . . ) { . . . }
public void setEndY ( . . . ) { . . . }
39 public void setEndXY ( . . . ) { . . . }

41 p u b l i c i n t g et Le ng th ( ) { . . . } // Length o f t h e l i n e
p u b l i c double getGradient ( ) { . . . } // G r a d i e n t i n r a d i a n s
43 }

Summary: There are two approaches that you can design a line, composition or inheritance.
”A line composes two points” or ”A line is a point extended with another point”. Compare
the Line and LineSub designs: Line uses composition and LineSub uses inheritance. Which
design is better?

13
HaQT Object-Oriented Programming

2.2 The Circle and Cylinder Classes Using Composition

Try rewriting the Circle-Cylinder of the previous exercise using composition (as shown in
the class diagram) instead of inheritance. That is, ”a cylinder is composed of a base circle
and a height”.

1 /∗ ∗
∗ Cylinder . java
3 ∗/
public c l a s s Cylinder {
5 p r i v a t e C i r c l e base ; // Base c i r c l e , an i n s t a n c e o f C i r c l e c l a s s
p r i v a t e double height ;
7

// C o n s t r u c t o r with d e f a u l t c o l o r , r a d i u s and h e i g h t
9 public Cylinder () {
b a s e = new C i r c l e ( ) ; // Call the constructor to construct the Circle
11 height = 1 . 0 ;
}
13 ......
}

Which design (inheritance or composition) is better?

14

You might also like