Private og offentlige attributter, getters og setters.
Når noen kan tømme bankkontoen din
Du har lært å lage klasser med attributter og metoder. Men det lå en bombe under det hele: alle attributtene var direkte tilgjengelige utenfra. Forestill deg en bankkonto der hvem som helst kan skrive konto.saldo = -1000000 og dermed ødelegge hele logikken. Metoden ta_ut, som du skrev så omhyggelig for å sjekke om det var nok penger, blir plutselig meningsløs – saldoen kan jo bare overstyres.
Løsningen heter innkapsling: prinsippet om å skjule intern data og bare eksponere det som er nødvendig. Dette er en av de fire grunnpilarene i OOP, sammen med arv, polymorfisme og abstraksjon. Innkapsling betyr å pakke data og metoder sammen i en klasse og samtidig skjule den interne implementasjonen fra omverdenen.
Formålet er firedelt: vi vil beskytte data mot ugyldig tilgang, kontrollere endringer ved å validere før vi lagrer, skjule kompleksitet så brukeren slipper å vite hvordan ting fungerer internt, og gjøre vedlikehold enklere ved at vi kan endre intern logikk uten å bryte ekstern kode.
Private attributter, getter og setter
I Python markerer vi tilgangsnivå med understreker foran navnet. self.navn er offentlig og kan aksesseres hvor som helst. self._navn med én understrek er beskyttet – en konvensjon som sier «intern bruk, ikke rør». self.__navn med to understreker er privat, og Python utfører såkalt name mangling som gjør det vanskelig å nå utenfra. Men merk deg: Python har ikke ekte private attributter slik Java og C++ har. Dette er konvensjoner og hindringer, ikke jernlås. Pythons filosofi er «we're all consenting adults here» – vi stoler på at utviklere respekterer konvensjonene.
Med et privat attributt beskytter vi saldoen og tvinger fram bruk av metoder som validerer:
class Bankkonto:
def __init__(self, kontonummer, saldo=0):
self.kontonummer = kontonummer
self.__saldo = saldo # privat
def hent_saldo(self):
return self.__saldo
def sett_inn(self, belop):
if belop > 0:
self.__saldo += belop
def ta_ut(self, belop):
if 0 < belop <= self.__saldo:
self.__saldo -= belopMetoden hent_saldo kalles en getter – den henter verdien. Metoder som sett_inn og ta_ut, som endrer verdien med validering, fungerer som settere. Nå kan ingen sette saldoen til en ugyldig verdi direkte; de må gå gjennom de validerte metodene.
Properties – den pythoniske eleganzen
Å skrive konto.hent_saldo() hver gang føles tungvint. Python har en mye mer elegant løsning: properties. En property gjør at en metode oppfører seg som et attributt. Vi bruker dekoratoren @property for getteren og @attributt.setter for setteren:
@property
def saldo(self):
return self.__saldo
@saldo.setter
def saldo(self, verdi):
if verdi >= 0:
self.__saldo = verdi
else:
raise ValueError("Saldo kan ikke være negativ")Nå skriver brukeren konto.saldo for å lese og konto.saldo = 1500 for å sette – det ser ut som vanlig attributt-tilgang, men bak kulissene kjører validering. Det er det fineste med properties: enkel syntaks utad, full kontroll inni.
Properties er også perfekte for beregnede verdier som ikke lagres, men regnes ut når du trenger dem. En Person med fornavn og etternavn kan ha en property fullt_navn som returnerer f"{self.fornavn} {self.etternavn}". Endrer du fornavnet, oppdateres det fulle navnet automatisk neste gang du leser det – fordi det aldri ble lagret, bare beregnet. Vil du derimot ha et read-only-attributt som kan leses men ikke endres utenfra, lager du bare en getter uten setter. Et produkts antall_solgt kan da bare økes gjennom en selg-metode, aldri settes direkte.
Information hiding – og når du faktisk trenger det
Information hiding handler ikke om å være hemmelighetsfull. Det handler om fire praktiske gevinster. Det reduserer kompleksitet, fordi brukeren slipper å vite hvordan saldo lagres internt. Det forhindrer feil, fordi ingen ved et uhell kan sette en ugyldig verdi. Det muliggjør endringer: du kan bytte intern representasjon – for eksempel lagre saldo i øre i stedet for kroner for bedre presisjon – uten at koden som bruker klassen merker noe, så lenge getteren returnerer kroner. Og det tvinger riktig bruk av API-et, fordi private attributter krever at brukere går via dine validerte metoder. Merk at information hiding handler om design og vedlikehold, ikke om hastighet – properties kan til og med ha litt overhead.
Men ikke alle klasser trenger streng innkapsling. Bruk private attributter når attributtet må valideres, når det inngår i beregninger som må være konsistente, når du vil reservere retten til å endre intern representasjon, eller når det er kritisk for objektets integritet. Offentlige attributter er helt greit for enkle data uten logikk, som koordinater x og y, for rene datastrukturer, og for intern kode som ingen andre skal bruke. En god tommelfingerregel: start enkelt med offentlige attributter, og gjør dem private med properties først når du faktisk trenger validering eller kontroll.
Oppsummering
Vi startet med en bankkonto hvem som helst kunne tømme, og endte med full kontroll over dataene. Innkapsling betyr å skjule intern data og styre tilgangen. Private attributter markeres med __attributt, beskyttede med _attributt, mens offentlige attributter står uten understrek. Getter og setter er metoder som leser og endrer private attributter, gjerne med validering.
Det pythoniske grepet er @property, som gir elegant attributt-syntaks utad og full kontroll inni, og @attributt.setter for å definere setteren. Properties egner seg også for beregnede verdier og for read-only-attributter uten setter. Bak alt ligger information hiding – idéen om at å skjule interne detaljer gir enklere vedlikehold, færre feil og frihet til å endre. Men husk: ikke alt trenger innkapsling. Start enkelt, og lås ned først når du faktisk trenger validering. I neste kapittel skal vi se på arv – hvordan klasser kan bygge videre på hverandre.
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.