De ontvangen relatie bewaren
Vul Person.__init__(name, address) in: bewaar name precies en bewaar hetzelfde ontvangen Address-object op address. Kopieer dit adres hier bewust niet. De Address-klasse in de starter is al compleet.
Een boek heeft een auteur, en meerdere boeken kunnen dezelfde auteur hebben. Je kunt die relatie in je gegevensmodel zichtbaar maken. Daarbij moet je bewust kiezen of de boeken één auteur delen of ieder een zelfstandig auteursobject bewaren.
Compositie betekent dat een object andere objecten gebruikt als onderdelen. Een Book kan bijvoorbeeld een Author in het attribuut author bewaren. Met book.author.name volg je eerst de relatie naar de auteur en lees je daarna diens naam.
Beide delen zijn gewone objecten met hun eigen toestand. Het buitenste object kan die toestand gebruiken, maar maakt het binnenste object niet vanzelf opnieuw. Je eerdere kennis van verwijzingen blijft dus van toepassing.
class Author:
def __init__(self, name):
self.name = name
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
writer = Author("Ada")
book = Book("De reis", writer)
print(book.title)
print(book.author.name)De reis Ada
Je hoeft de auteursnaam daardoor niet op iedere plek als los veld te herhalen. Het model laat zien welk gegeven bij het boek hoort en welk gegeven bij de auteur. Een extra methode kan via die relatie een leesbare beschrijving maken.
Wanneer twee boeken hetzelfde Author-object ontvangen, bewaren zij volgens dit voorbeeld dezelfde verwijzing. Een wijziging aan de auteur is dan via beide boeken te zien. Dat is passend als zij werkelijk één gedeelde auteur voorstellen.
class Author:
def __init__(self, name):
self.name = name
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
writer = Author("Ada")
first = Book("De reis", writer)
second = Book("Het vervolg", writer)
writer.name = "Ana"
print(first.author.name)
print(second.author.name)
print(first is second)
print(first.author is second.author)Ana Ana False True
| Verwijzing | Object waarnaar zij verwijst |
|---|---|
| first.author | De gedeelde auteur |
| second.author | Dezelfde gedeelde auteur |
Een nieuwe Book is hier wel een nieuw buitenste object. Dat feit zegt nog niets over de identiteit van zijn onderdelen. Je moet bij een kopie dus ook onderzoeken wat er met die binnenste verwijzingen gebeurt.
Soms vraagt het contract juist dat een wijziging aan een kopie het origineel niet raakt. Dan maak je zowel een nieuw buitenste object als de benodigde nieuwe onderdelen. Bij een eenvoudig adresmodel kun je de bestaande adresvelden lezen en daarmee een nieuw Address maken.
Je hoeft daarvoor niet ieder object in het hele programma blind te kopiëren. Bepaal welke delen van dit model eigen toestand moeten krijgen. Onveranderlijke tekstwaarden kunnen worden overgenomen zonder een nieuwe veranderlijke gegevensstructuur te delen.
Person(original.name, original.address) kan een nieuwe persoon maken die nog hetzelfde adres bevat. Wanneer je daarna via de kopie de stad wijzigt, verandert het gedeelde adres ook voor de oorspronkelijke persoon. De buitenste identiteiten zijn verschillend, maar de innerlijke identiteit is nog dezelfde.
Een waardevergelijking van de beginvelden vindt deze fout niet. Beide adressen bevatten aanvankelijk dezelfde stad en straat. Daarom controleren de opdrachten ook de echte objectverwijzingen en het gedrag na een wijziging.
In deze oefening ontvangt Person bewust een bestaand Address en bewaart precies die verwijzing. Het lezen van de stad volgt de relatie naar dat adres. Een verhuisbewerking verandert de stad op het bestaande adres; de naam en straat blijven behouden.
Twee personen die bewust dat adres delen, zien dus dezelfde verhuizing. Dat is de gekozen afspraak voor deze handeling. Het is geen automatische regel dat ieder gegevensmodel zijn adres altijd moet kopiëren.
copy_person heeft juist een ander contract: zij maakt een nieuwe persoon met een nieuw adres en dezelfde beginvelden. Een verhuizing van die kopie mag het originele adres niet veranderen. Bewaar tekst exact en voeg geen eigen normalisatie- of validatieregels toe.
Vul Person.__init__(name, address) in: bewaar name precies en bewaar hetzelfde ontvangen Address-object op address. Kopieer dit adres hier bewust niet. De Address-klasse in de starter is al compleet.
Maak city_of(person) die de city van het adres van deze persoon precies teruggeeft. Verander de naam, straat of stad niet en voeg geen opschoonregel toe.
Maak move(person, city) die de city op het bestaande adres van person verandert en None teruggeeft. Behoud naam, straat en adresidentiteit. Twee personen die dit adres delen moeten dezelfde verhuizing zien.
Maak copy_person(person) die een nieuwe Person met een nieuw Address en precies dezelfde naam, straat en stad teruggeeft. Een wijziging aan het adres van de kopie mag het oorspronkelijke adres niet raken.
Hierna combineer je eigen toestand, objectgedrag en foutpaden in een reserveringsmodel.
Voer je code uit en ontdek
wat je hebt gemaakt.
Je hoeft het niet in één keer goed te doen. Na het uitvoeren zie je hier welke stappen al kloppen.