Komplett pensumoversikt for objektorientert programmering ved UiO — med forklaringer, sentrale begreper, eksamenstips og vanlige fallgruver. Eksamensoptimalisert basert på tidligere eksamener.
IN1010 Objektorientert programmering er et sentralt emne ved Institutt for informatikk, UiO, som bygger videre på IN1000. Kurset undervises i Java og dekker hele spekteret av OOP: fra arv og polymorfisme via grensesnitt og generics til egendefinerte datastrukturer (lenkede lister, stabler, køer, trær) og flertrading. Eksamen er en 4-timers praktisk prove der du skriver Java-kode for hånd eller digitalt.
Eksamen følger et svært forutsigbart mønster: du får et sammenhengende scenario (en samling tog med vogner, en flyformasjon, et hotell med rom, et bilkollektiv, en konkurransegruppe med seilfly osv.) og skal bygge opp et klassehierarki rundt det. De siste årene (V2022, V2023, V2024) har strukturen vært nesten identisk fra ar til ar -- bare konteksten skifter. Den faste malen er fem oppgaver: (1) tegn klassehierarkiet med en abstrakt overklasse på toppen og et Motordrevet-lignende interface, (2) programmer klassene og interfacet, (3) skriv en beholderklasse som holder objektene i en (typisk dobbelt-)lenket liste med metodene leggTil, taUt, finnOgTaUt, en iterator og en metode som returnerer en typet array, (4) egendefinert unntak + en rekursiv metode, (5) en monitor med tråder. Typisk vekting: klassehierarki og OOP (20-25%), lenket liste + iterator (30-40%), unntak + rekursjon (15-20%), og tråder/monitor (20-36%).
Viktigste enkeltinnsikt: nyere eksamener krever at monitoren skrives med ReentrantLock og Condition (lock()/unlock(), await()/signal()) -- IKKE med synchronized/wait/notify. Oppgaveteksten sier ofte eksplisitt "bruk Condition og ReentrantLock; ikke bruk synchronized". Oev derfor monitor-mønsteret med lås og betingelsesvariabel.
Du trenger ikke skrive kjørbar kode (med unntak av V2020-typen hjemmeeksamen). Sensor vurderer om du viser forståelse for OOP-prinsipper, korrekt bruk av arv/grensesnitt, og evne til å manipulere referanser i lenkede lister korrekt. Sensorveiledningene gjentar at smafeil (manglende semikolon, tilgangsmodifikatorer, import) ignoreres -- men at løsninger som "bærer preg av å være hentet fra andre programmer" uten forståelse ikke gir uttelling. Skriv tydelig og vis at du forstår referansemanipuleringen.
Klassehierarkier med extends og abstract, metodeoverstyring med @Override, og polymorfisme der en superklassereferanse kan peke på subklasseobjekter. Grunnmuren i all objektorientert programmering i Java.
Arv (inheritance) lær en klasse arve felt og metoder fra en annen klasse. Subklassen utvider superklassen med nyckelsordet extends. Java støtter kun enkel arv -- en klasse kan bare ha en direkte superklasse. All felles funksjonalitet legges i superklassen, mens spesialisert oppførsel defineres i subklassene.
Polymorfisme betyr at en referanse av typen superklasse kan peke på et objekt av en subklasse. Når du kaller en metode på denne referansen, er det objektets faktiske type som bestemmer hvilken versjon av metoden som kjøres. Dette kalles dynamisk binding (eller sen binding) og er en av de mest kraftfulle mekanismene i OOP. I praksis betyr det at du kan skrive kode som behandler alle objekter av en superklassetype likt, uten å vite den konkrete subklassen på kompileringstidspunktet.
En abstrakt klasse kan ikke instansieres direkte -- du kan ikke skrive new AbstraktKlasse(). Den kan inneholde både konkrete metoder (med full implementasjon) og abstrakte metoder (deklarert med abstract, uten kropp). Subklasser må implementere alle abstrakte metoder, ellers må de også være abstrakte selv. Abstrakte klasser er ideelle når du vil tvinge subklasser til å tilby en bestemt oppførsel, men samtidig dele felles kode.
På eksamen V2021 var klassen Sti en naturlig abstrakt klasse: alle stier har lengde og to endepunkter, men de konkrete typene (Kjerrevei, Natursti) er ulike. På V2021 var klassen Aktivitet også abstrakt, med en abstrakt metode handling() som subklassen Turgaaer implementerte.
Når du oppretter et objekt av en subklasse, kalles superklassens konstruktor først via super(...). Hvis du ikke kaller super() eksplisitt, legger Java automatisk inn et kall til den parameterlose konstruktoren. Husk: super() må være første linje i konstruktoren. Dersom superklassen bare har en konstruktor med parametere, må subklassen kalle super(parametere) eksplisitt -- ellers kompilerer ikke koden.
private: kun tilgjengelig i egen klasse -- bruk dette for instansvariabler. protected: tilgjengelig i egen klasse, subklasser og klasser i samme pakke -- nyttig når subklasser trenger direkte tilgang. public: tilgjengelig overalt. Pakke-tilgang (ingen modifikator): tilgjengelig i hele pakken, men ikke utenfor. På V2021 ble det spesifisert at instansvariablene i Aktivitet ikke skulle være private fordi klassene Simulator og PrioKo trengte direkte tilgang (de la i samme pakke).
Nesten alle eksamener starter med å be deg tegne klassehierarkiet. Bruk UML-konvensjoner: rektangler for klasser, heltrukket pil fra subklasse til superklasse for arv, stiplet pil for interface-implementering. Abstrakte klasser og metoder markeres med kursiv skrift. Tegningen gir typisk 5-6% av totalpoengene og er enkle poeng. Det typiske hierarkiet har tre nivær: en abstrakt overklasse på toppen (f.eks. en "Kjoretoy"-aktig basisklasse), to-tre klasser på nivå to (hvorav en gjerne også er abstrakt), og konkrete klasser på nivå tre som implementerer et interface (typisk kalt Motordrevet, Elektrisk, Kjokken e.l.).
Et stadig tilbakevendende krav (V2022) er at alle klassene skal overstyre toString() slik at den tar med verdiene av alle instansvariablene (unntatt liste-pekerne). Den polymorfe teknikken er at hver subklasse først kaller super.toString() for å få med superklassens felt, og deretter legger til sine egne felt. Slik unngar du å gjenta felles felt i hver subklasse. Husk å skrive ut noe som identifiserer den konkrete typen (f.eks. "Suite: ..." vs "EnkeltRom: ...").
// Abstrakt superklasse
abstract class Sti {
private int lengde; // meter
private Kryss ende1, ende2;
Sti(int lengde, Kryss e1, Kryss e2) {
this.lengde = lengde;
this.ende1 = e1;
this.ende2 = e2;
e1.leggTilSti(this);
e2.leggTilSti(this);
}
Kryss finnAndreEnde(Kryss denne) {
if (denne == ende1) return ende2;
return ende1;
}
int beregnGaaTid(int fart) {
return lengde / fart;
}
}
// Konkrete subklasser -- ingen forskjell annet enn navn
class Kjerrevei extends Sti {
Kjerrevei(int lengde, Kryss e1, Kryss e2) {
super(lengde, e1, e2);
}
}
class Natursti extends Sti {
Natursti(int lengde, Kryss e1, Kryss e2) {
super(lengde, e1, e2);
}
}// Sti-referanse kan peke pa bade Kjerrevei og Natursti
Sti[] stier = new Sti[3];
stier[0] = new Kjerrevei(500, kryss1, kryss2);
stier[1] = new Natursti(800, kryss2, kryss3);
stier[2] = new KjerreveiMedUtsikt(300, kryss1, kryss3, 5);
for (Sti s : stier) {
// Dynamisk binding: riktig versjon av metoden kalles
int tid = s.beregnGaaTid(80);
System.out.println("Tid: " + tid + " min");
// Bruk instanceof for a sjekke spesifikk type
if (s instanceof GodUtsikt) {
GodUtsikt u = (GodUtsikt) s;
System.out.println("Utsikt: " + u.hentUtsiktsVerdi());
}
}abstract class Rom {
final int romnr, kvm, sengeplasser, etasje;
Rom neste; // liste-peker (tas IKKE med i toString)
Rom(int romnr, int kvm, int senger, int etasje) {
this.romnr = romnr; this.kvm = kvm;
this.sengeplasser = senger; this.etasje = etasje;
}
@Override
public String toString() {
return "romnr=" + romnr + ", kvm=" + kvm
+ ", senger=" + sengeplasser + ", etasje=" + etasje;
}
}
class Suite extends Rom {
Suite(int romnr, int kvm, int senger, int etasje) {
super(romnr, kvm, senger, etasje);
}
@Override
public String toString() {
// Kall superklassens toString og legg til type foran
return "Suite: " + super.toString();
}
}Nøkkelformler
Vanlige feil
Eksamenstips
Laster...