22 Objektorientert programmering
Grunnleggende OOP-konsepter: klasser, objekter, metoder og arv.
Hva er objektorientert programmering?
Objektorientert programmering (OOP) er en måte å strukturere kode ved å modellere "ting" fra den virkelige verden som objekter.
Hvorfor OOP?
- Bedre organisering av kode
- Lettere å gjenbruke kode
- Enklere å vedlikeholde store programmer
- Naturlig måte å tenke på problemer
Grunnleggende begreper:
Klasse
En "oppskrift" eller mal for å lage objekter. Definerer hvilke egenskaper (attributter) og handlinger (metoder) objektene skal ha.
Objekt (instans)
En konkret "ting" laget fra en klasse. Hvert objekt har sine egne verdier for attributtene.
Eksempel fra virkeligheten:
- Klasse: "Sensor" (generell oppskrift)
- Objekter: temperatursensor1, temperatursensor2, fuktighetssensor1
Attributter
Egenskaper/data som objektet har:
- sensor.verdi = 23.5
- sensor.type = "temperatur"
- sensor.enhet = "celsius"
Metoder
Handlinger objektet kan utføre:
- sensor.les()
- sensor.kalibrer()
- sensor.rapport()
Definere klasser i Python
Grunnleggende klassesyntaks:
class Sensor:
"""En klasse som representerer en sensor."""
def __init__(self, sensor_id, sensor_type):
"""Konstruktør - kjøres når objekt opprettes."""
self.sensor_id = sensor_id
self.sensor_type = sensor_type
self.verdi = 0.0
self.aktiv = True
def les_verdi(self):
"""Leser og returnerer sensorverdien."""
# I virkeligheten ville dette lese fra hardware
return self.verdi
def sett_verdi(self, ny_verdi):
"""Setter en ny verdi (for simulering)."""
self.verdi = ny_verdi
def __str__(self):
"""Returnerer tekstrepresentasjon."""
return f"{self.sensor_type} ({self.sensor_id}): {self.verdi}"Opprette objekter:
# Lage sensor-objekter
temp_sensor = Sensor("T001", "temperatur")
fukt_sensor = Sensor("H001", "fuktighet")
# Bruke objektene
temp_sensor.sett_verdi(23.5)
fukt_sensor.sett_verdi(65)
print(temp_sensor.les_verdi()) # 23.5
print(fukt_sensor) # fuktighet (H001): 65self-parameteren:
- Refererer til objektet selv
- Må være første parameter i alle metoder
- Brukes for å få tilgang til attributter og andre metoder
Metoder og attributter
Instansattributter
Tilhører hvert enkelt objekt.
class Motor:
def __init__(self, pin):
self.pin = pin # Instansattributt
self.hastighet = 0 # InstansattributtKlasseattributter
Deles mellom alle objekter av klassen.
class Motor:
antall_motorer = 0 # Klasseattributt
def __init__(self, pin):
self.pin = pin
Motor.antall_motorer += 1
m1 = Motor(5)
m2 = Motor(6)
print(Motor.antall_motorer) # 2Private attributter (konvensjon)
Attributter som starter med eller _ er ment som "private".
class Konto:
def __init__(self, saldo):
self._saldo = saldo # "Privat" - bruk med forsiktighet
def ta_ut(self, belop):
if belop <= self._saldo:
self._saldo -= belop
return True
return False
def vis_saldo(self):
return self._saldoProperty-dekoratøren
Kontrollert tilgang til attributter.
class Temperatur:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, verdi):
if verdi < -273.15:
raise ValueError("Under absolutt null!")
self._celsius = verdi
@property
def fahrenheit(self):
return self._celsius * 9/5 + 32
t = Temperatur(20)
print(t.celsius) # 20
print(t.fahrenheit) # 68.0
t.celsius = 25 # Setter via propertyArv og polymorfisme
Arv
En klasse kan arve fra en annen og få alle dens egenskaper.
class Sensor:
"""Baseklasse for alle sensorer."""
def __init__(self, sensor_id):
self.sensor_id = sensor_id
self.verdi = 0.0
def les(self):
return self.verdi
class TemperaturSensor(Sensor):
"""Arvende klasse - temperaturspesifikk."""
def __init__(self, sensor_id, enhet="celsius"):
super().__init__(sensor_id) # Kall foreldres konstruktør
self.enhet = enhet
def les_formatert(self):
return f"{self.verdi} °{'C' if self.enhet == 'celsius' else 'F'}"
class FuktighetsSensor(Sensor):
"""Arvende klasse - fuktighetsspesifikk."""
def les_formatert(self):
return f"{self.verdi} %RH"super()
Brukes for å kalle metoder fra foreldreklassen.
Polymorfisme
Objekter av forskjellige klasser kan behandles likt.
def les_alle_sensorer(sensorer):
for sensor in sensorer:
print(sensor.les_formatert()) # Fungerer for alle sensortyper!
temp = TemperaturSensor("T001")
fukt = FuktighetsSensor("H001")
temp.verdi = 23.5
fukt.verdi = 65
les_alle_sensorer([temp, fukt])
# 23.5 °C
# 65 %RHFordeler med arv:
- Unngår kodeduplisering
- Logisk hierarki
- Lettere å utvide funksjonalitet
Definer en klasse LED med attributter pin og status (på/av), og metoder for slaapaa(), slaaav() og toggle().
Hva er forskjellen mellom en klasse og et objekt?
Lag en klasse DCMotor med attributter for pin og hastighet (-100 til 100), og metoder for sett_hastighet(n), stopp(), og retning().
Forklar hva self betyr i Python-klasser.
Hva gjør super()._init_() og når brukes det?
Design et klassehierarki for et smarthus-system. Lag en baseklasse SmartEnhet og arvede klasser for SmartLys, SmartTermostat og SmartLaas. Inkluder relevante attributter og metoder.
Lag en klasse SensorLogg som holder styr på målinger over tid. Den skal kunne legge til målinger med tidsstempel, hente siste n målinger, beregne gjennomsnitt, og finne min/max.
Oppgaver
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.