Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Expand
titleDel 4 - ExamRequirement-klassen og IExamRequirement-grensesnittet (25%)

ExamRequirement-klassen (se vedlegg 3) representerer en sjekk for om et Exam-objekt, altså en avlagt eksamen, tilfredsstiller visse krav. F.eks. kan en lage et ExamRequirement-objekt som sjekker om en har fått minst C i TDT4100. Selve testen gjøres av accepts-metoden, som sjekker det angitte Exam-argumentet mot verdiene som ligger i ExamRequirement-objektet selv.

Oppgave a)

Skriv ferdig konstruktør nr. 2, og gjør den så kort og enkel som mulig.

Expand
titleLF
Code Block
public ExamRequirement(String course, int sinceYear) {
   this(course, sinceYear, 'E');
}
Oppgave b)

accepts-metoden m/hjelpemetoden acceptsCourse er ferdigskrevet, men koden inneholder (minst) tre feil. Skriv korrekt kode.

Expand
titleLF

Sammenligningen må gjøre med emnekode (String) mot emnekode (String), ikke emnekode (String) mot emne (Course), og da må også equals brukes. Testen på årstallet må snus (>= tilsvare ikke mindre enn).

Code Block
private boolean acceptsCourse(Course course) {
   return this.course.equals(course.getCode()) && course.getYear() >= sinceYear;
}
Oppgave c)

Nederst i klassen er feltet atLeastCInTdt4100 deklarert. Med koden atLeastCInTdt4100.accepts(...) skal en kunne sjekke om en har minst C i TDT4100. Skriv ferdig deklarasjonen, både modifikator(er) og initialiseringsuttrykket.

Expand
titleLF
Code Block
public final static ExamRequirement atLeastCInJava = new ExamRequirement("TDT4100", 0, 'C');
Oppgave d)

Du trenger å sjekke om en eksamen er for et masteremne på IDI, som har kode som begynner på ”TDT42”, f.eks. TDT4250. Forklar hvordan du kan bruke arv for å organisere koden og hvordan eksisterende kode evt. må endres.

Expand
titleLF

I acceptsCourse så sammenlignes navn med equals, mens vi trenger å sammenligne med startsWith. En kan lage en protected-metode kalt acceptsCourseCode i ExamRequirement, som kalles av acceptsCourse og som brukes equals. Så redefineres denne metoden i en subklasse, hvor en bruker startsWith.

I ExamRequirements:

Code Block
private boolean acceptsCourse(Course course) {
   return acceptsCourseCode(course.getCode()) && course.getYear() >= sinceYear;
}

protected boolean acceptsCourseCode(String course) {
   return course.equals(this.course);
}


I subklassen:

Code Block
@Override
protected boolean acceptsCourseCode(String course) {
   return course.startsWith(this.course);
}
Oppgave e)

Skriv kode for et funksjonelt grensesnitt IExamRequirement, som ExamRequirement (allerede implisitt) implementerer. Forklar hvorfor et slikt grensesnitt kan være nyttig, fremfor å bare ha ExamRequirement-klassen.

Expand
titleLF

Med funksjonelt menes et grensesnitt med bare én metode (og denne metoden gir samme resultat for om den kalles flere ganger på samme exam-objekt). Her er det bare én mulig metode i ExamRequirement som er aktuell som grensesnitt-metoden. Bruk av et slikt grensesnitt gir større frihet i hvilke krav en kan implementere og hvordan det gjøres.

Code Block
public interface IExamRequirement {
   public boolean accepts(Exam exam);
}
Oppgave f)

Skriv en alternativ deklarasjon av atLeastCInTdt4100 som har IExamRequirement som type og utnytter Java 8 sin funksjonssyntaks i initialiseringsuttrykket.

Expand
titleLF
Code Block
public static IExamRequirement atLeastCInJave = (exam) -> "TDT4100".equals(exam.getCourse().getCode()) && exam.getGrade() ><= 'C';
Expand
titleAppendix 1: Class overview

 

...

Expand
titleAppendix 3: Provided code (fragments)
Code Block
public class Course {
     
      ... fields, constructors and methods for code and credits ...
     
      public int getYear() {  ... }
     
      public char getSemester() { ... }
 
      /**
       * Gets the time this Course is given, in the format <semester><year>
       * E.g. if the semester is 'S' and the year is 2016,
       * it should return S2016.
       */
      public String getTime() { ... }
     
      /**
       * Sets the time that this Course is taught. The format is the semester
       * (char) followed by the year. The year may be shortened to two digits;
       * if it is below 50 then 2000 should be added, otherwise 1900.
       * E.g. S16 means Spring 2016, while F86 means Fall 1986.
       * @param time The time in the format <semester><year>
       * @throws IllegalArgumentException if the format is incorrect
       */
      public void setTime(String time) {
            ...
      }
}
 
public class Exam {
 
      ... fields and methods for course and grade ...
    
      /**
       * Initialises an Exam, by setting the course and grade.
       * The grade can only be set to one of the characters 'A'-'F'.
       * @throws IllegalArgumentException if the grade is not legal
       */
      public Exam(...) { ... }
 
     /**
      * Tells whether this Exam has a result that is a passing grade.
      */
     public boolean isPass() { ... }
}


public class Person {

      ... fields, constructors and methods for name ...
     
      /**
       * Adds a Course to this Person, if no Course is registered
       * for the same code, year and semester.
       * @param course
       * @return true if the course was added, false otherwise
       */
      public boolean addCourse(Course course) { ... }
     
      /**
       * Returns whether this Person has a Course with the given code.
       * @param code
       */
      public boolean hasCourse(String code) { ... }
 
      /**
       * Creates and adds an exam to this Person for the provided Course and
       * with the provided grade, but only if this Person has this Course and
       * no passing Exam is registered for that Course.
       * @param course
       * @param grade
       * @return the newly created and added Exam, or null
       */
      public Exam addExam(Course course, char grade) { ...  }
 
      /**
       * Gets the exam that was registered last for the provided course code.
       * This is the exam that counts for that course!
       * @param course
       */
      public Exam getLastExam(String code) { ... }
 
      /**
       * Returns true of this Person has passed the Course for the provided code.
       * @param code
       */
      public boolean hasPassed(String code) { ... }
     
      /**
       * Counts the credits this Person has earned.
       */
      public double countCredits() { ... }
}


/**
 * Represents a requirement concerning an Exam for a specific Course.
 * The Exam's result must not be before the provided year (sinceYear) and
 * the grade must not be worse than the provided grade (minGrade).
 */
public class ExamRequirement {
 
      public final String course;
      public final int sinceYear;
      public final char minGrade;
 
      public ExamRequirement(String course, int sinceYear, char minGrade) {
            this.course = course;
            this.sinceYear = sinceYear;
            this.minGrade = minGrade;
      }
 
      /**
       * Initialises with the course and year with provided data and
       * makes sure a passing grade is required.
       * @param course
       * @param sinceYear
       */
      public ExamRequirement(String course, int sinceYear) { ... }
 
      /**
       * Helper method for checking the course
       * @param course
       */
      private boolean acceptsCourse(Course course) {
            return this.course == course && sinceYear > course.getYear();
      }
 
      /**
       * Returns true if the provided Exam is for the specified course,
       * not before the specified year and not worse than the specified grade.
       * @param exam
       * @return
       */
      public boolean accepts(Exam exam) {
            return acceptsCourse(exam.getCourse()) && exam.getGrade() ><= minGrade;
      }
 
      // declares atLeastCInTdt4100
      ... ExamRequirement atLeastCInTdt4100 = ...;
}