Versions Compared

Key

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

...

Vi ser altså at alle objektene er instanceof Book og at book1 ikke er instanceof de to subklassene. Hvis en altså sier at et objekt er en instans av en bestemt type T, så betyr det ikke nødvendigvis at en brukte new T(...) for å lage den, men new <T eller en subklasse av T>(...). Dette er analogt med at en kan si at et objekt er en instans av (grensesnittet) Iterator, selv om en en nødvendigvis ikke har brukt new Iterator(...) for å opprette objektet. Hvis en ønsker å si nettopp det at en brukte new T(...) så kan en kanskje si at objektet ble instansiert med som T.

Situasjonen er nokså tilsvarende med deklarasjoner og tilordninger. Når en deklarerer en variabel (eller felt eller parameter) til å være av en type T, så sier en at denne variablen bare kan tilordnes instanser av T, eller mer presist, at den bare kan tilordnes verdien av uttrykk som har typen T. I koden under vises ulike tilfeller og kommentaren angir om det er lov eller ikke og hvorfor.

...

Code Block
public class Book {

   private String title;

   public Book(String title) {
      setTitle(title);
   }

   public String getTitle() {
      return title;
   }

   public void setTitle(String title) {
      if (! <sjekk at title bare inneholder bokstaver og tall>) {
          throw new IllegalArgumentException("Book titles can only contain letters and digits");
      }
      this.title = title;
   }
}
Code Block
// Feil!!!

public class Dictionary {

   private int wordCount;

   // ingen initialisering av title
   public Dictionary(int wordCount) {
      this.wordCount = wordCount;
   }

   // egen validering av title
   public void setTitle(String title) {
      if (! <sjekk at title slutter på 'ordbok'>) {
          throw new IllegalArgumentException("Dictionary titles must end with 'ordbok'");
      }
      this.title = title;
   }
}
Code Block
// Riktig!!!

public class Dictionary {

   private int wordCount;

   // ingentitle initialiseringinitialiseres av titlemed super(...)
   public Dictionary(String title, int wordCount) {
      // kall først superklassens konstruktør
      super(title);
      this.wordCount = wordCount;
   }

   // egenbruker validering av titlesuperklassens setTitle-metode
   public void setTitle(String title) {
      if (! <sjekk at title slutter på 'ordbok'>) {
          throw new IllegalArgumentException("Dictionary titles must end with 'ordbok'");
      }
      super.setTitle(title);
   }
}

...

Code Block
public class Book {

   protected String title;

   ...

   public void setTitle(String title) {
      if (! ...) {
          throw new IllegalArgumentException(...);
      }
      this.title = title;
   }
}
Code Block
public class Dictionary {

   ...

   public void setTitle(String title) {
      if (! ...) {
          throw new IllegalArgumentException(...);
      }
      // fordi title-attributtet er deklarert med protected,
      // så har vi nå lov til å endre det direkte
      this.title = title;
   }
}

...

Bruk og

...

redefinering av metoder

En annen teknikk for å la en subklasse definere alternative regler for oppførsel, er å skille ut logikk i egne metoder som kan redefineres. Anta f.eks. at en forutser behovet for å definere subklasse-spesifikke regler for gyldige title-verdier. Dette kan håndteres som vist under:

Code Block
public class Book {

   private String title;

   ...

   protected boolean isValidTitle(String title) {
      return <true hvis title bare inneholder bokstaver og tall, og false ellers>
   }

   public void setTitle(String title) {
      if (! isValidTitle(title)) {
          throw new IllegalArgumentException(...);
      }
      this.title = title;
   }
}
Code Block
public class Dictionary {

   ...

   @Override
   protected boolean isValidTitle(String title) {
      return <true hvis title slutter på 'ordbok', og false ellers>
   }
}

I Book-koden over har en lagt valideringslogikken i en egen isValidTitle-metode, som er gjort synlig for subklassene med protected-modifikatoren. Dictionary-klassen redefinerer denne metoden med sin egen logikk. Hvis en kaller setTitle på et objekt instansiert som Book, så vil Book-klassen sin isValidTitle-metode bli kalt. Men dersom objektet er en Dictionary-instans, så vil (den redefinerte) metoden i Dictionary-klassen bli brukt i stedet. Dermed kan Dictionary-spesifikke valideringsregler overstyre valideringsreglene i Book, som jo var intensjonen. Dictionary-klassen får altså fortsatt ikke direkte tilgang til title-attributtet, men får lov til å endre/overstyre valideringslogikken.

Ved hjelp av protected-modifikatoren og redefinering av metoder kan altså en superklasse tillate at visse regler endre/overstyres av en subklasse. Dersom subklassen ønsker å bruke reglene til superklassen, så kan en (selektivt) bruke metodekall med super-nøkkelordet. Dictionary-klassen kan f.eks. kalle super.isValidTitle(title) hvis den ønsker å (gjen)bruke superklassens logikk.