Arv og polymorfi, del 3 Abstrakte klasser Formlene for å regne ut arealet er forskjellig for sirkel, kvadrat og trekant



Yüklə 445 b.
tarix22.11.2017
ölçüsü445 b.
#11537


Arv og polymorfi, del 3


Abstrakte klasser

  • Formlene for å regne ut arealet er forskjellig for sirkel, kvadrat og trekant.

  • Men arealet kan beregnes for alle typer figurer.

  • Metoden finnAreal() er polymorf (= ”mangeformet, som opptrer i mange former”).

  • Metoden er abstrakt i klassen Figur (ikke mulig å finne en formel som gjelder for alle figurer).

  • Klassen er abstrakt fordi den inneholder en abstrakt metode.

  • Det er ikke mulig å lage objekter av en abstrakt klasse.



Modifikatoren abstract

  • Abstrakt klasse:

    • abstract class Materiale { ….osv.
    • kan ikke lage objekter av en abstrakt klasse
    • behøver ikke inneholde eller arve abstrakte metoder
    • kan inneholde både abstrakte og konkrete metoder
  • Abstrakt metode:

    • abstract metodehode;
    • En klasse som arver, eller selv deklarerer en abstrakt metode, må deklareres som abstrakt.


Hva hvis polymorfi ikke hadde eksistert?

  • Hva gjør polymorfien for oss?

    • I det siste eksemplet lar den oss håndtere ulike typer geometriske figurer under ett.
    • Vi sender en melding til et objekt som tilhører en subklasse av Figur.
    • Objektet vet selv hvordan arealet skal regnes ut.
  • Hva hvis objektet ikke selv visste hvilken formel som skulle brukes?

    • Da måtte vi bruke if-else-if, omtrent slik:
      • if (figur instanceof Sirkel) {
      • ... formel for å beregne arealet av en sirkel …
      • }
      • else if (figur instanceof Kvadrat) {
      • ... formel for å beregne arealet av et kvadrat …
      • } else {
      • ... formel for å beregne arealet av en trekant …
      • }
  • Tenk deg om en gang til dersom du tror at du trenger å bruke instanceof kombinert med en if-else-if-else-sekvens.

    • Du bør da vurdere om det er bedre å lage en abstrakt metode i en felles superklasse for de involverte klassene, og så la hver enkelt klasse få sin egen implementasjon av metoden


Når har vi behov for å bruke operatoren instanceof?

  • Vi trenger å bruke instanceof i i de tilfellene der vi skal sende melding til kun en del av et subtre.

  • Vi lager følgende objekter:

    • A objekt1 = new C();
    • A objekt2 = new E();
  • Vi kan trygt sende meldingen metode1() til begge objektene:

    • objekt1.metode1();
    • objekt2.metode1();
  • Meldingen metode2() kan vi bare sende til subklasser til klassen B:

    • if (objekt1 instanceof B) {
    • B etObjekt = (B) objekt1;
    • etObjekt.metode2();
    • }


Eksempel



Oppgaver til forelesningen

  • Gå gjennom kildekoden så langt (vedlagt)

  • Ferdigstill de metodene som mangler i klassen Personregister

    • public boolean endreLønn(long fnrAns, int nyttLønnstrinn) {
      • return true;
      • }
    • public boolean registrerNyttFag(long fnrStud, String nyttFag) {
      • return true;
      • }
    • public boolean settKarakter(long fnrStud, String fagnr, char nyKarakter) {
      • return true;
      • }
    • public char finnKarakter(long fnrStud, String fagnr) {
      • return UGYLDIG_FNR;
      • }


Tilgangsmodifikatorer

  • Definisjonsområdet til et navn er den delen av programmet der navnet kan brukes uten at det må kvalifiseres.

  • Tilgjengeligheten til et navn utenfor definisjonsområdet er bestemt av om det står private, public, protected eller ingenting foran navnet (ingenting = package).

  • Klasser:

    • Alle klasser vi har laget hittil, unntatt appletene, har vært tilgjengelig kun i den pakken der de var deklarert.
    • Appletene har hatt public foran seg. De er tilgjengelig fra overalt.


Tilgjengeligheten til konstruktører og medlemmer deklarert i klassen C



Anbefalt bruk av tilgangsmodifikatorer

  • Objektvariabler og klassevariabler er alltid private.

  • Konstanter er vanligvis offentlige, men kan være private dersom de ikke er av interesse for andre enn klassen selv.

  • Konstruktører er vanligvis offentlige.

  • Metoder er vanligvis private eller offentlige.

  • Konstruktører og metoder kan være beskyttede dersom det ikke har noen mening å bruke dem utenfor subklasser.

  • Klasser har i utgangspunktet pakketilgang (ingen tilgangsmodifikator). Dette begrenser også tilgangen til offentlige konstruktører og medlemmer i klassen. Klasser som skal tas i bruk generelt, gjøres offentlige og legges i en navngitt pakke. Da vil automatisk alle offentlige konstruktører og medlemmer også bli offentlige.



Det reserverte ordet super

  • super kan brukes på to måter:

    • I en konstruktør for å anrope konstruktøren rett over i klassetreet, eksempel fra forrige forelesning:
      • public OppgaveDag(int startNr, String startNavn, int startAntTimer, int startDato) {
      • super(startNr, startNavn, startAntTimer);
      • dato = startDato;
      • }
      • Kallet på super() må være første setning i konstruktøren.
      • Argumentlisten til super() må være i samsvar med parameterlisten til en konstruktør i superklassen.
    • I en hvilken som helst metode kan vi bruke super som kvalifikator for å henvise til et skjult eller erstattet navn i en superklasse, eksempel:
      • public String toString() {
      • return super.toString() + ", dato: " + dato;
      • }
      • Vi kan ikke skrive super.super() eller lignende for å anrope konstruktør eller metode på mer enn ett nivå over i klassetreet.


Konstruktører

  • Dersom vi ikke kaller en bestemt konstruktør i den direkte superklassen ved å anrope super(), vil standardkonstruktøren i superklassen anropes.

  • Dersom denne ikke eksisterer, vil kompilatoren gi en feilmelding.

  • Dersom det ikke har mening å lage objekter av en klasse, kan det forhindres på to måter:

    • Lag klassen abstrakt. Dette brukes dersom klassen har eller kan ha subklasser.
    • Lag alle konstruktører private. Dette brukes dersom klassen ikke kan ha subklasser (den er final, se nedenfor).


Referanser og casting

  • En referanse til en klasse kan settes til å peke til objekter av en subklasse til klassen. Den kan ikke settes til å peke til objekter av en superklasse.

    • Person personen =new Student(12106078756L, "Ole Pettersen", "Storgt 3, 7001 Trondheim", 1234567L); // ok
    • Ansatt læreren = new Student(12106078756L, "Ole Pettersen", "Storgt 3, 7001 Trondheim", 1234567L); // ikke ok
    • Ansatt læreren = new Person(12106078756L, "Ole Pettersen", "Storgt 3, 7001 Trondheim"); // ikke ok
  • Anta at vi har en referanse til et objekt.

    • Referansen kan castes til den klassen objektet tilhører, eller til superklasser av denne klassen.
    • Det er ikke tillatt å caste referansen til en subklasse av den klassen som objektet tilhører.
    • Ugyldig casting gir ClassCastException.
    • Object etObjekt = new Student(12106078756L, "Ole Pettersen", "Storgt 3, 7001 Trondheim", 1234567L); // ok
    • Student enStudent = (Student) etObjekt;
    • Ansatt enAnsatt = (Ansatt) etObjekt; // ikke ok
    • Person enPerson = (Person) etObjekt; // ok


Modifikatoren final

  • final forhindrer subklassing og erstatning.

  • En final metode kan ikke erstattes eller skjules:

    • public final double finnBredde() {
    • return breddePåBelegg;
    • }
  • Det er ikke mulig å subklasse en final klasse:

    • final class AnnenSortBelegg extends Belegg2 {
    • ….osv.


Å erstatte eller skjule et navn

  • Å erstatte (”override”) en arvet objektmetode

    • Hvis en klasse deklarerer en objektmetode, vil denne deklarasjonen erstatte en eventuell arvet metode med samme signatur.
    • Kompilatoren gir feilmelding dersom returtypen ikke stemmer og/eller tilgangsnivået er mindre strengt enn i den erstattede metoden.
    • Hvordan blir det hvis signaturen ikke stemmer?
    • En objektmetode kan ikke erstatte en arvet klassemetode.


Interface

  • Et interface er en samling med metodehoder.

  • En klasse kan velge å implementere et interface. Den må da programmere alle metodene i interfacet.

  • Eksempel på interface:

    • public interface Comparable<Type> { // tilhører pakken java.lang
    • public int compareTo(Type obj);
    • }
  • Eksempel på klasse som implementerer interfacet:

    • class Flate implements Comparable {
    • ... objektvariabler ...
    • public int compareTo(Flate denAndreFlaten) {
    • double areal1 = finnAreal();
    • double areal2 = denAndreFlaten.finnAreal();
    • if (Math.abs(areal2 - areal1) < toleranse) return 0;
    • else if (areal1 < areal2) return -1;
    • else return 1;
    • }
    • ... andre metoder i klassen ...
    • }


Å lage egne interface



Implementasjon av interfacet



Bruk av klassen FireSifretHeltall

  • En referanse av en interface-type kan referere til objekter som tilhører en klasse som implementerer interfacet:

    • Sammenligningsbar tall1 = new FireSifretHeltall(700);
    • Sammenligningsbar tall2 = new FireSifretHeltall(1700);
  • Vi kan nå bare sende meldinger deklarert i interfacet til objektet:

    • System.out.println(tall1.størreEnn(tall2)); // ok
    • System.out.println(tall1.finnVerdi()); // ikke ok


Mer aktuell bruk av interface

  • Grensesnittet som klienten skal forholde seg til spesifiseres via interface, eksempel figur/FigurInterface.java

      • package figur;
      • public interface FigurInterface {
      • double finnAreal();
      • }
  • Klassene legges i pakker og gis pakketilgang, eksempel filen figur/Figur.java:

      • package figur;
      • abstract class Figur implements FigurInterface {
      • /* Alle figurer kan beregne sitt eget areal */
      • public abstract double finnAreal();
      • }
      • class Kvadrat extends Figur { ...
  • Klienter lager objekter vhja fabrikkmetoder, se neste side



Fabrikken er en offentlig klasse

  • Filen figur/Figurfabrikk.java

    • package figur;
    • public class Figurfabrikk {
    • public static FigurInterface lagKvadrat(int side) {
    • return new Kvadrat(side);
    • }
    • public static FigurInterface lagTrekant(double grunnlinje, double høyde) {
    • return new Trekant(grunnlinje, høyde);
    • }
    • public static FigurInterface lagSirkel(double radius) {
    • return new Sirkel(radius);
    • }
    • }


Testklient

  • import figur.*;

  • class TestInterface {

  • public static void main(String[] args) {

  • FigurInterface enSirkel = Figurfabrikk.lagSirkel(10);

  • FigurInterface enTrekant = Figurfabrikk.lagTrekant(5, 6);

  • FigurInterface etKvadrat = Figurfabrikk.lagKvadrat(4);

  • /* Arealer hver for seg */

  • System.out.println("Arealet til sirkelen: " + enSirkel.finnAreal());

  • System.out.println("Arealet til trekanten: " + enTrekant.finnAreal());

  • System.out.println("Arealet til kvadratet: " + etKvadrat.finnAreal());

  • /* Behandler så alle figurene under ett */

  • FigurInterface[] figurtabell = new FigurInterface[3];

  • figurtabell[0] = enSirkel;

  • figurtabell[1] = enTrekant;

  • figurtabell[2] = etKvadrat;

  • for (FigurInterface fig : figurtabell) {

  • System.out.println("Arealet er " + fig.finnAreal()

  • + " for " + fig.getClass().getName()); // henter klassenavnet

  • }

  • }

  • }




Yüklə 445 b.

Dostları ilə paylaş:




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2022
rəhbərliyinə müraciət

    Ana səhifə