0% found this document useful (0 votes)
63 views7 pages

Home Assignment - Week 4 (OOP 2) : 0. Warm-Up: Shapes Hierarchy

The document describes an assignment to create a class hierarchy for shapes and an online store. For shapes, it involves creating classes for shapes like Circle and Rectangle that inherit from an abstract Shape class and implement interfaces like Growable and Movable. It explores composition vs inheritance for a Cylinder class and uses generics. For an online store, it involves creating classes like Customer, Address, Product, and subclasses of Discount like PercentageDiscount. A Cart class contains a customer, products, and discounts with methods to add/remove them.

Uploaded by

Cosmin Grosu
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)
63 views7 pages

Home Assignment - Week 4 (OOP 2) : 0. Warm-Up: Shapes Hierarchy

The document describes an assignment to create a class hierarchy for shapes and an online store. For shapes, it involves creating classes for shapes like Circle and Rectangle that inherit from an abstract Shape class and implement interfaces like Growable and Movable. It explores composition vs inheritance for a Cylinder class and uses generics. For an online store, it involves creating classes like Customer, Address, Product, and subclasses of Discount like PercentageDiscount. A Cart class contains a customer, products, and discounts with methods to add/remove them.

Uploaded by

Cosmin Grosu
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/ 7

Home Assignment - Week 4 (OOP 2)

0. Warm-up: Shapes Hierarchy


You are given a ​Point​ class, (with 2 coordinates ​x,y​, getters, immutable, can compute distance
to other point)

Try to complete the steps below in such a way to reuse the Point class and avoid any code
repetition:

a) ​Create an ​abstract class​ ​Shape​, with methods:


- ​double computeArea()
- ​boolean isLargerThan(Shape other)​ - should return true if area of this > area of other
- question: should you / can you mark these methods as ​abstract​? what about ​private​? ​final​?

b) ​Create a ​CircleShape​ ​class​, extending Shape, which represents a circle of certain radius
- also override ​toString()​ for it, for convenience
- q: what fields should it have? constructors? any getters needed? other methods?
what can/should we use as access level for each?
could or should we make the class abstract? what about final?..

- Create a ​RectangleShape​ ​class​, extending Shape, which represents a rectangle of specific


height and width
- same questions as for CircleShape
- q: do you notice any code duplication already? (​isLargerThan​?) can we avoid that in anyway?

c) ​We want to be able to resize our 2 shapes.


- create a ​Growable​ ​interface​, with one method:
- ​void grow(double factor)​ - when called, it should resize current shape by this factor (size =
size * factor)
- change CircleShape and RectangleShape so they support the methods of the new interface

d)​ We want to position our shapes in 2D space, be able to move them and measure distances
between them.
- create an ​interface​ ​Movable​, with methods:
- Point getCenter();
- void setCenter(Point center);
- void move(double deltaX, double deltaY)​ - should move the center point of the shape
adding deltaX/Y to its current x/y
- double distanceTo(Movable other)​ - the distance between the center of this shape and
center of other

- create 2 new ​classes​, named ​Circle ​/ ​Rectangle​, which are similar to CircleShape /
RectangleShape, but also support the actions from Movable interface
- how can you reuse existing classes/interfaces to minimize the amount of new code to
write?
- did you need to change anything in existing classes/interface? (how much, and why)
- is there still any code duplication between circle/rectangle classes? can it be avoided?

e) ​Create a new ​class​ ​Square​, which is similar to Rectangle, but always has the width the same
as height
- how can you reuse existing classes/interfaces to minimize the amount of code needed for
the new class? how many methods do you still need to write in Rectangle class?
- which of the existing classes/methods can we make final now? (respond before trying it in
code) would we have any reasons/benefits to do this?

​ rowUntilBiggerThan​(double targetArea, double


f) ​We would like to add a new ​method​: ​void g
factor)​, which repeatedly grows a shape (by the given factor), until its area is bigger than
targetArea.
Where (and how) should we add this method, so it can be used by concrete shape classes
(Square,Circle,..), without repeating its implementation more than once?.. (do we need to
change our class hierarchy? how?)

g)​ If we would need to add a new ​Elipse​ shape in the future, where would you include it
in this class hierarchy? (should it be above/below Circle/CircleShape? why?)
(note: an Elipse is basically an elongate shape, and unlike a circle it has 2 differet radiuses -
see: ​https://www.math24.net/circle-ellipse​ )

h)​ Would it be a good idea to make ​Point​ itself ​movable​ (remove final, add setters or a move()
method)? Could we then remove the setCenter() from Movable? Can this cause any possible
problems later? (think about 2 shapes build using same center point, them moved.. what would
the distance between them be?)

i)​ Could we avoid somehow the need to repeat the declaration of the ​'center'​ field (and
setter/getter for it) in each Shape?.. ​(hint: think about role/content of the Movable interfaces,
Shape class)

j) Optional​: draw an UML class diagram for all these classes/interfaces, either on paper or
using an app.
(UML info: ​https://medium.com/@smagid_allThings/uml-class-diagrams-tutorial-step-by-step-520fd83b300b​,
Online tools: ​https://www.draw.io/​, ​https://online.visual-paradigm.com/solutions/free-class-diagram-tool/​,
https://creately.com​ , Offline: ​https://wiki.gnome.org/Apps/Dia​)
1. Circle & Cylinder​ (composition vs inheritance)
a. Define a ​Circle​ ​class​ (fields: centerX/Y,radius; methods: area(), length(), toString(),
getters)
- hint: circle area = PI*R^2, length = 2*PI*R ; may use Math.PI, Math.pow.. if
needed
- question: can you make the fields final? (can you think of any benefits it might
bring?) What about the methods and/or the class itself?

b. Based on it, define a ​CylinderH​ ​class​, first using ​inheritance​ (no composition)
- with 2 constructors:
- Cylinder(double centerX, double centerY, double radius, double height)
- Cylinder(Circle circle, double height)
- Can you avoid repeating code between constructors? (hint: try to
use this())
- members: similar to Circle (inherited), but also with some extra fields (height) and
extra methods: volume(), getBase() (returns a Circle representing the base),
getHeight()
- hint: volume = base area * height
- question: for volume(), can you use the existing area() method?
- question: do all inherited methods make sense as they are for Cylinder?
(like: area(), length(), toString())
- now override methods to better fit Cylinder logic: area(), toString()
- hint: cylinder surface area = 2*base area + h*base perimeter
- question: can we use area() from Circle for computing area() for Cylinder,
instead of repeating that code? how?..
- question: after overriding area(), is the volume() still working correctly? if
not: why, and how can we fix it?
- question: can we reuse Circle.toString() when overriding toString() for
cylinder?
- question: what can we do with length(), as its really not relevant/needed anymore
for Cylinder? (hide it somehow? return some special value?..)

c. Now solve it again, but using ​composition​ (instead of inheritance) and creating a different
class​ named ​CylinderC ​(which should NOT extend Circle, but should instead contain a
Circle field…)
- question: does it look better/simpler, or worse that 1st? any pluses/minuses?

d. Define a ​Cylinder​ generic i​ nterface​, and define in it the common properties of CylinderH
and CylinderC
- modify the 2 classes so that both of them implement this interface
- question: how many lines did you need to change in the 2 classes?
- question: does client code which wants to work with one of our 2 cylinder
implementations need to still mention the name of one of the 2 classes
(CylinderH/CylinderC), or can it use only Cylinder name everywhere? (if
class names are still needs, where exactly?)

e. Is it possible to further reduce duplication between the 2 classes? Is there any code
which you could move from the 2 cylinder implementation classes to the interface itself,
(reducing duplication) AND which would remain correct in the future, even if we add
other type of cylinder classes implementing this interface? (hint: see ‘default’ methods)
- is there any difference between the 2 classes, regarding how easy is to move
some of their code to the interface?..
- is any client code affected by such a move, what do you think?
- do all the tests still pass? (check after you did the moving)

f. Optional​: draw an UML class diagram for all these classes/interfaces.

2. Online Store
Write a class hierarchy for an online store. Please define and implement the following packages,
entities, fields and methods:

● customer​ package:
○ Customer​ class:
■ fields: firstName, lastName, cnp, address (this one should be of type
Address, see below)
○ Address​ class:
■ fields: street, streetNumber, town
● product​ package:
○ Product​ class:
■ fields: id, name, type (ex: clothing, electronics etc), price, color

● discount​ package:
○ Discount​ - class, abstract class or interface? it should allow the code to
somehow be able to apply a discount in a general way, and then support 2 types
of discounts (two implementations with compute the discount in different ways):
○ PercentageDiscount​ class
■ field: percent: what percentage of the price should be discounted (e.g 4%)
■ methods ?
○ FixedDiscount​ class
■ field: amount: a fixed amount (e.g 35 RON)
■ methods ?
Use inheritance to somehow define/support these two different discount types.
● (directly in top package of assignment)
○ Cart​ class:
■ fields: customer, list of products and discounts
■ methods:
● Cart(Customer customer) - constructor 
● void addProduct(Product p) 
● void removeProduct(Product p) 
● void addDiscount(Discount d) 
● void removeDiscount(Discount d) 
● double computeProductsPrice() ​ - compute total price of
products (without any discounts applied)
● double computeTotalPrice() ​ - compute final cart price
(total price of products + all discounts applied)
● String g ​enerateInvoice()​ - should return a String (multi-line,
use “\n” to separate lines) representing the invoice for current cart;
it should contain this info:
○ Customer info
○ List of products
○ Total products price (without discounts)
○ List of discounts
○ Total amount (total products price + discounts)

Testing
Run the provided unit tests, and run some of your own (unit or manual)

Other Considerations
This hierarchy can be implemented and extended in many ways. Some suggestions are:
● Create a ​Store​ entity that holds all products and available discounts
● Both Discounts and Products can be added to the cart, so they could both implement a
common “​CartItem​” interface. Think about what it could contain (the common behavior
for Discounts and Products) and update your code accordingly.
● A Cart can hold products and discounts either in separate arrays (or ArrayList), or it can
simply use a single array/list of CartItems. Think about the advantages and
disadvantages of both approaches.

3. Complex Numbers
Create a ​Complex​ class that represents a complex number (more info:
https://en.wikipedia.org/wiki/Complex_number​ )
It should have the following methods:
- Complex add(Complex other)​ :​adds this and other number and returns a new
Complex instance; hint: (a+bi) + (c+di) = (a+c) + (b+d)i
- Complex negate()​: r​ eturns a new Complex number representing the negative value of
this; hint: if z = (a+bi) then -z = (-a-bi)
- Complex multiply(Complex other)​ :​returns a new complex number that is equal
to this * other number; hint: (a+bi)(c+di) = (ac−bd) + (ad+bc)i
- boolean equals(Object other)​ : should return true only if ‘other’ is also an
instance of Complex class and the 2 numbers are equal (both their parts..)
- String toString()​ :​ should return strings such as “3 + 4i”

- static Complex complex(double real, double imaginary)​ : should create a


new Complex instance with given values; this will be basically just a shortcut for users of
this class to create instances in a more concise manner (calling ‘complex(..)’ vs ‘new
Complex(...)’)

Testing:
Run the provided unit tests. May also run some tests of your own (manual or unit)

Optional:

4. MyList interface
Starting from the solved problems 6,7 from previous week (implementing MyArrayList and
MyLinkedList)
- define a new interface named ​MyList​ which contains the common behavior between
your 2 list implementations
- Question: what methods should you add to it?
- Change your 2 list classes so that they implement the new interface
- How many lines of code did you need to change? (more than 1?)
- Do all the tests for each list class still pass? (you did write your own unit tests for
them, didn’t you? :)...)
- Does any client code which wants to use one of your 2 list implementations need
to care/know which one is working one? (beside the very first step when it calls
the constructor of one or the other)
- Based on this, can you (re)write your tests in such a way that you test
both implementations by the same test code? (hint: in the test method you
will need some different code to create 2 different instances, one of
MyArrayList and one of MyLinkedList, but after this they can be tested by
exactly same code - meaning some assert…() methods grouped in a
single private method in test class, etc.. )

5. Linked lists specializations


Based on the solved problem from previous week for MyLinkedList, implement these classes
based/derived from that class (somehow - inherit from it if possible, or make that one more
general, or just copy part of the code, etc..):

Doubly linked list​:


● each element has two links - one to the next and one to the previous node

Stack​ - a linked list with the following restrictions:


● adding new nodes only at the head of the list
● remove nodes only from the head of the list
● can access only the element from the head of the list

Queue​ - a linked list with the following restrictions:


● adding new nodes only at the tail (end) of the list
● remove nodes only from the head of the list
● can access only the element from the head of the list
Implement these specializations of a linked list in such a way that you take advantage of OOP
features like inheritance and polymorphism.

6. Other exercises
For more exercises/practice with OOP concepts, read and try to solve exercises from here,
especially the exercises ​1.2​ (Book and Author) and ​5.1​ (The Discount System):

http://swarm.cs.pub.ro/~vdobrota/oop/

You will see used there some diagrams, representing the structure of the Java classes, named
UML diagrams​.
- They are used here mainly to show the structure of the classes (class name,
private/public fields and methods) and also some relations between them (extends/uses,
meaning ‘is a’ / ‘has a’).
- UML is a standard widely used in the industry, and it can be useful to be able to read
(even create) such diagrams.
For a ​short​ ​tutorial​ about UML, see:
https://medium.com/@smagid_allThings/uml-class-diagrams-tutorial-step-by-step-520fd83b300b

You might also like