Tilbake
2.1
Komposisjon og aggregering

2.1 Komposisjon og aggregering

Bygge komplekse objekter med komposisjon.

60 min
6 oppgaver
KomposisjonAggregeringHas-a-relasjon
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 6 oppgaver

Komposisjon og aggregering

Du har lært om arv, der ein klasse er ein spesialisering av ein annan. Men ofte ønskjer vi at ein klasse har ein annan som del av seg sjølv. Dette vert kalla komposisjon eller aggregering, og er eit kraftig alternativ til arv.

I dette kapittelet skal du lære korleis du byggjer komplekse objekt ved å kombinere enklare objekt, og kvifor "favor composition over inheritance" er eit viktig designprinsipp.

Definisjon
Komposisjon er når eitt objekt inneheld eitt eller fleire andre objekt som ein del av tilstanden sin. Vi seier at objektet har ein relasjon til dei andre objekta.

Aggregering er ei svakare form for komposisjon der inneheldne objekt kan eksistere uavhengig av container-objektet.

Delegering tyder å overlate ansvar til eit innebygd objekt i staden for å arve oppførsel.

✏️Eksempel

Eksempel: Bil har ein motor

I staden for at Bil arvar frå Motor, kan vi la Bil ha ein Motor:

class Motor:
    def __init__(self, hestekrefter):
        self.hestekrefter = hestekrefter
        self.kjorer = False

    def start(self):
        self.kjorer = True
        print(f"Motor med {self.hestekrefter} hk startet!")

    def stopp(self):
        self.kjorer = False
        print("Motor stoppet.")

class Bil:
    def __init__(self, merke, hestekrefter):
        self.merke = merke
        self.motor = Motor(hestekrefter)  # Komposisjon!

    def start_bil(self):
        print(f"{self.merke} starter...")
        self.motor.start()  # Delegering

    def stopp_bil(self):
        self.motor.stopp()
        print(f"{self.merke} stoppet.")

# Bruk
min_bil = Bil("Tesla Model 3", 450)
min_bil.start_bil()
# Output:
# Tesla Model 3 starter...
# Motor med 450 hk startet!

Her har Bil ein Motor, og delegerer start/stopp-oppgåver til han.

Definisjon
Favor composition over inheritance er eit velkjent designprinsipp som seier:

"Føretrekk å byggje funksjonalitet ved å kombinere objekt (komposisjon) framfor å arve oppførsel (arv)."

Fordelar med komposisjon:
- Meir fleksibel – kan endre oppførsel ved runtime
- Lausare kopling – objekt er mindre avhengige av kvarandre
- Enklare testing – kan enkelt byte ut delar
- Unngår problem med djupt arvshierarki

✏️Eksempel

Eksempel: Komposisjon vs. arv

Med arv (mindre fleksibelt):

class Flygende:
    def fly(self):
        print("Flyr!")

class Svømmende:
    def svøm(self):
        print("Svømmer!")

class And(Flygende, Svømmende):  # Multippel arv
    pass

# Hva om vi vil ha en and som ikke kan fly?
# Må lage ny klasse...

Med komposisjon (meir fleksibelt):

class FlyOppførsel:
    def utfør(self):
        print("Flyr!")

class SvømOppførsel:
    def utfør(self):
        print("Svømmer!")

class IngenFlyOppførsel:
    def utfør(self):
        print("Kan ikke fly.")

class And:
    def __init__(self, fly_oppførsel, svøm_oppførsel):
        self.fly_oppførsel = fly_oppførsel
        self.svøm_oppførsel = svøm_oppførsel

    def fly(self):
        self.fly_oppførsel.utfør()

    def svøm(self):
        self.svøm_oppførsel.utfør()

# Nå kan vi enkelt lage forskjellige ender:
and1 = And(FlyOppførsel(), SvømOppførsel())
and1.fly()  # Flyr!

and2 = And(IngenFlyOppførsel(), SvømOppførsel())
and2.fly()  # Kan ikke fly.

Med komposisjon kan vi byte oppførsel utan å lage nye klassar!

✏️Eksempel

Eksempel: Aggregering vs. komposisjon

Komposisjon (tight kopling): Hjarte eksisterer ikkje utan person.

class Hjerte:
    def __init__(self, bpm):
        self.hjerteslag_per_minutt = bpm

    def slå(self):
        print(f"Hjerte slår {self.hjerteslag_per_minutt} ganger/min")

class Person:
    def __init__(self, navn):
        self.navn = navn
        self.hjerte = Hjerte(70)  # Lager hjertet her

# Når person slettes, slettes også hjertet

Aggregering (laus kopling): Bil kan ha hjul, men hjul kan eksistere separat.

class Hjul:
    def __init__(self, størrelse):
        self.størrelse = størrelse

class Bil:
    def __init__(self, hjul_liste):
        self.hjul = hjul_liste  # Får hjul utenfra

# Hjul kan eksistere uavhengig av bil
hjul1 = Hjul(18)
hjul2 = Hjul(18)
hjul3 = Hjul(18)
hjul4 = Hjul(18)

min_bil = Bil([hjul1, hjul2, hjul3, hjul4])
# Hjulene eksisterer fortsatt selv om bil slettes

I praksis vert begge termane ofte brukte om kvarandre.

✏️Eksempel

Eksempel: Delegering i praksis

Lat oss byggje eit enkelt Spill-system med komposisjon:

class Grafikk:
    def tegn_skjerm(self, tekst):
        print(f"🎮 {tekst}")

class Lyd:
    def spill_effekt(self, lyd):
        print(f"🔊 {lyd}")

class Inndata:
    def les_tast(self):
        return input("Trykk tast > ")

class Spill:
    def __init__(self):
        self.grafikk = Grafikk()
        self.lyd = Lyd()
        self.inndata = Inndata()
        self.poeng = 0

    def start(self):
        self.grafikk.tegn_skjerm("Spillet starter!")
        self.lyd.spill_effekt("Start-musikk")

        while True:
            kommando = self.inndata.les_tast()

            if kommando == "a":
                self.angrip()
            elif kommando == "q":
                self.avslutt()
                break

    def angrip(self):
        self.grafikk.tegn_skjerm("Du angriper!")
        self.lyd.spill_effekt("Sverd-lyd")
        self.poeng += 10
        print(f"Poeng: {self.poeng}")

    def avslutt(self):
        self.grafikk.tegn_skjerm("Spillet avsluttes...")
        self.lyd.spill_effekt("Avslutt-musikk")

# Bruk
# spill = Spill()
# spill.start()

Spelet har grafikk-, lyd- og inndata-objekt, og delegerer ansvar til dei.

Oppsummering

I dette kapittelet har du lært:

- Komposisjon tyder at ein klasse inneheld objekt av andre klassar ("har-en")
- Aggregering er ei svakare form der inneheldne objekt kan eksistere uavhengig
- Delegering er å overlate ansvar til inneheldne objekt
- "Favor composition over inheritance" – føretrekk komposisjon for fleksibilitet
- Komposisjon gir lausare kopling og gjer kode meir vedlikehaldbar

Neste steg: Vi skal bruke komposisjon til å byggje datastrukturar!

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.