Composition
Putting Things Together¶
Start by doing Task 4
We now need to combine this new class with our Sample
.
In a picture, the current situation looks something like this:
We have two classes that are lying around without any relation to each other.
What we want to achieve is that the Location
class represents a location in which a sample was found.
This can be achieved by introducing a new attribute found_at
into the Sample
class which will be given as a Location
-instance when creating a new Sample
.
Such a way of combining classes is called composition.
# If you put the "Location"-class into in its own file,
# make sure to import it before use
class Sample:
def __init__(self, identifier, collector, found_at):
… # All the other attributes
self.found_at = found_at
… # Everything else as before
# Let's try to use this
galapagos = Location(latitude=-0.777259, longitude=-91.142578)
my_sample = Sample(identifier="0123", collector="Darwin", found_at=galapagos)
# When composing a model of multiple classes, you can chain the "."-operator
print(my_sample.found_at.latitude)
print(my_sample.found_at.longitude)
This is how it would look like in a diagram:
We read this as: a Sample
is composed of a Location
via the found_at
attribute.
For future convenience, we have put the Location
-class into its own file, called location.py
.
If we want to use attributes or methods of the Location
-class in our Sample
-class, we have to add
Sample
-class.
Note: A benefit of putting classes into their own files is to keep programs organized and split them into dedicated pieces that can be easier handled on their own. In technical terms we talk about concerns and responsibilities: A class of type
DnaSequencer
should not include concerns and responsibilities of a class representing aLocation
. This means, that for example handling of the coordinates has nothing to do with sequencers and, the other way around, analysing DNA has nothing to do with the location where a sample was taken. In general we want to achieve a so-called Separation of Concerns and make each class adhere to the paradigma of having a single responsibility.
Let’s assume we also want to provide a few default locations for easier use. Our file could now look something like this:
class Location:
… # As before
# A few default locations that we often visit
# Notice that we indicate them to be constants by naming them in UPPER_CASE
DRESDEN = Location(latitude=51.05089, longitude=13.73832)
GALAPAGOS = Location(latitude=-0.777259, longitude=-91.142578)
NORTH_POLE = Location(latitude=90, longitude=0)
NAURU = Location(latitude=-0.5284144, longitude=166.9342384)
By defining these constants, we can now refer to location.DRESDEN
in our code, which is a lot easier than repeating the coordinates all over or defining them each time we need them.