0%

Overerving en polymorfisme · eindproject

Eindproject: Project: ondersteun meerdere vraagtypen

De cursus begon met een quiz waarvan de vragen dictionaries waren, allemaal in dezelfde vorm, gecontroleerd door één functie die de regel kende. Dit hoofdstuk eindigt met een quiz die vier soorten vragen bevat en wordt beoordeeld door code die geen van die soorten kent.

Wat je bouwt

Question          the base: prompt, points, optional collaborators
  TextQuestion    matches ignoring spaces and case
  ChoiceQuestion  matches one option
  NumericQuestion matches within a tolerance
  SurveyQuestion  ungraded, always correct

TimeLimit         a thing a question has
Hint              a thing a question has

Quiz              holds questions of any kind
ScoreReport       turns an attempt into lines

Vier subklassen omdat elk een werkelijk andere soort is, één niveau diep. Twee samenwerkingspartners omdat timing en hints vrij combineren met alle vier.

De belofte die elke subklasse nakomt

is_correct(response) ontvangt elke mogelijke string en geeft True of False terug. De methode gooit nooit een exceptie op en geeft nooit iets anders terug.

Die zin is de reden dat Quiz en ScoreReport één keer kunnen worden geschreven. De beoordelaar controleert die voor elke subklasse met een leeg antwoord en een onzinantwoord. Dat is de eenvoudige versie van de familietest die hoofdstuk 13 goed opbouwt.

SurveyQuestion wordt niet beoordeeld en is altijd juist. Waarom is die een subklasse in plaats van een afzonderlijke niet-verwante klasse?

Regels die de beoordelaar controleert

  • Geen functie buiten de klassen gebruikt isinstance of noemt een subklasse.

  • Elke subklasse geeft voor elke string een booleaanse waarde terug uit is_correct.

  • describe() wordt één keer geschreven, op de basis.

  • Geen enkele klasse drukt iets af.

  • Een vijfde soort vraag, bedacht door de beoordelaar, werkt overal zonder wijziging.

Die laatste is de echte toets van dit hoofdstuk. Als een klasse die na jouw code is geschreven, door iemand die die nooit zag, correct wordt beoordeeld en gerapporteerd, doet het ontwerp wat het beloofde.

Afronden

Lees je voltooide Quiz en ScoreReport en tel hoe vaak ze een specifiek soort vraag noemen. Het antwoord moet nul zijn.

Bedenk daarna een vijfde soort. Een waar-of-onwaarvraag, een trefwoordvraag die meerdere schrijfwijzen accepteert of een bereikvraag werken allemaal. Voeg die toe aan de quiz zonder Quiz of ScoreReport aan te passen. Dat nieuwe gedrag door het ongewijzigde programma zien stromen is de eindstreep van het project.

Opdracht

De gevalideerde samenwerkingspartners en basisklasse zijn gegeven. Bouw de concrete familie en de twee klassen die die gebruiken zonder concrete typen te kennen.

Question(prompt, points, timing=None, hint=None) bewaart de gedeelde toestand. describe() geeft "<prompt> (<points> points)" terug, gevolgd door de beschrijving van elke aanwezige samenwerkingspartner, timing vóór hint. is_correct(response) gooit NotImplementedError op. Voeg een property kind_label toe die "question" teruggeeft.

De vier subklassen overschrijven elk is_correct en kind_label, en geen ervan definieert describe opnieuw:

  • TextQuestion(prompt, points, answer, ...), label "text", vergelijkt zonder op spaties en hoofdletters te letten;

  • ChoiceQuestion(prompt, points, correct_option, ...), label "multiple choice", vergelijkt de optie met hoofdletters of kleine letters;

  • NumericQuestion(prompt, points, answer, tolerance, ...), label "numeric", binnen de tolerantie, en geeft False terug in plaats van een exceptie op te gooien als het antwoord geen getal is;

  • SurveyQuestion(prompt, ...), label "survey", 0 waard, altijd juist.

TimeLimit(seconds) en Hint(text) zijn gegeven en gevalideerd. Behoud ook de eerdere constructorregels: tekstantwoorden en keuzeopties mogen niet leeg zijn, de numerieke tolerantie moet niet-negatief zijn en een quiztitel moet niet-leeg zijn. Weiger deze ongeldige waarden met ValueError.

Quiz(title) bewaart vragen, geeft ze veilig terug en meldt question_count en total_points. ScoreReport(quiz, responses) geeft lines() terug: één "<description>: correct" of ": incorrect" per vraag, daarna "Score: <earned> of <total>", dan "Kinds: <labels, comma separated, in order, without repeats>".

Quiz.add(None) gooit ValueError op. Een rapport moet precies één antwoord per quizvraag ontvangen; lines() gooit ValueError op bij zowel te weinig als te veel antwoorden, zodat zip geen gegevens ongemerkt kan weggooien.

Elke is_correct moet voor elke mogelijke string True of False teruggeven en nooit een exceptie opgooien. Geen klasse drukt iets af en niets buiten de familie noemt een subklasse.