Overerving en polymorfisme · oefening
Gebruik polymorfe collecties
Een quiz bevat meerdere soorten vragen tegelijk. Hoofdstuk 6 gaf toevallig elke Question hetzelfde gedrag; Pythonlijsten zelf vereisten dat nooit. Nu doet de gedeelde bewerking er meer toe dan de concrete klasse:
Quiz is ongewijzigd ten opzichte van hoofdstuk 6. De klasse noemt nooit TextQuestion of ChoiceQuestion en hoeft dat ook niet: die bevat vragen en elke vraag kan zichzelf beschrijven en de eigen punten melden.
Een collectie waarvan de items van verschillende klassen zijn en via één gedeelde reeks bewerkingen worden gebruikt, is een polymorfe collectie. Het grootste deel van de waarde van de afgelopen vier lessen wordt hier zichtbaar. Het diagram toont ‘One call’, één aanroep, ‘For each question’, voor elke vraag. ‘The loop never checks the type’ zegt dat de lus nooit het type controleert. De tekstvraag normaliseert tekst (‘normalizes text’) en de meerkeuzevraag controleert een optie (‘checks an option’).

Een gemengde quiz beoordelen
Negen regels die anders een groeiende keten van typecontroles zouden zijn. Een numerieke vraag toevoegen verandert hier niets, en ook niets in Quiz of in het rapport.
Wat moet er in Quiz en score veranderen om een vierde soort vraag te ondersteunen?
Een gemengde collectie sorteren en filteren
De hulpmiddelen uit hoofdstuk 7 werken hier ongewijzigd. Het is nuttig ze op een gemengde lijst te zien, omdat ze daar hun plek verdienen:
Beide lezen points, dat elke vraag heeft. Geen van beide weet of geeft erom dat er verschillende klassen aanwezig zijn.
De verleiding om te kijken
Uiteindelijk lijkt iets echt het type nodig te hebben. Een rapport wil misschien tellen hoeveel meerkeuzevragen een quiz bevat:
choice_count = 0
for question in quiz.questions():
if isinstance(question, ChoiceQuestion):
choice_count = choice_count + 1
Dit werkt en het is de typeketen uit les 1 in een nieuw jasje. De klassenlijst is naar het rapport verhuisd en een niet-verwante klasse die hetzelfde meerkeuzegedrag biedt zou worden gemist. Subklassen van ChoiceQuestion zouden nog steeds aan deze controle voldoen.
Meestal is de duidelijke oplossing het object iets te vragen:
De kennis over wat elke klasse is blijft bij de klasse. Een nieuwe soort meerkeuzevraag toevoegen wordt een kwestie van wat die over zichzelf meldt, niet van elke isinstance in het programma vinden.
Dit is geen absolute regel. isinstance is prima aan een werkelijke grens, zoals bij het valideren van iets dat van buiten je programma binnenkomt. Binnen een familie die je zelf hebt ontworpen betekent het meestal dat een bewerking in de basis ontbreekt.
De oefening bouwt een quiz met vier soorten vragen en een rapport daarover, zonder typecontroles.
Opdracht
De gevalideerde vraagfamilie met vier soorten en de veilige collectie Quiz zijn gegeven. Bouw collectiebewerkingen die nooit vragen welk concreet soort ze hebben ontvangen.
Maak drie functies af:
graded_questions(quiz)geeft de vragen terug die meer dan nul waard zijn;count_of_kind(quiz, label)geeft terug hoeveel vragen dat label melden;report_lines(quiz, responses)geeft per vraag één regel"<description>: correct"of"<description>: incorrect"terug, daarna"Score: <points> of <total>".
Geen van de drie mag isinstance gebruiken of een subklasse noemen. De beoordelaar voegt een zelfbedachte vijfde soort vraag toe en verwacht dat alle drie die verwerken.