Metodien näkyvyys
Luokassa olevien metodien näkyvyyteen voidaan vaikuttaa samalla tavalla kuin attribuuttien näkyvyyteen. Jos metodin nimi alkaa kahdella alaviivalla __
, metodi ei ole näkyvissä asiakkaille.
Käytännössä mekanismia käytetään hiukan eri tavalla: piilotettujen attribuuttien käyttöä varten kirjoitetaan usein julkiset havainnointi- ja asetusmetodit. Piilotettu metodi on kuitenkin yleensä tarkoitettu vain luokan sisäiseen käyttöön, apumetodiksi asiakkaalta piilotettujen operaatioiden toteuttamiseksi.
Piilotettua metodia voidaan kutsua luokan sisällä normaalisti, mutta kutsuttaessa pitää muistaa self
-aluke. Tarkastellaan esimerkkinä sähköpostin vastaanottajaa mallintavaa luokkaa Vastaanottaja
, jossa yksityistä apumetodia käytetään tarkistamaan sähköpostiosoitteen oikeellisuus:
class Vastaanottaja:
def __init__(self, nimi: str, sposti: str):
self.__nimi = nimi
if self.__tarkasta_sposti(sposti):
self.__sposti = sposti
else:
raise ValueError("Sähköposti ei kelpaa")
def __tarkasta_sposti(self, sposti: str):
# Yksinkertainen tarkastus: osoitteessa on yli 5 merkkiä ja piste ja @-merkki
return len(sposti) > 5 and "." in sposti and "@" in sposti
Jos asiakas yrittää kutsua metodia, seuraa virhe:
pertti = Vastaanottaja("Pertti Keinonen", "pertti@example.com")
pertti.__tarkasta_sposti("jokumuu@example.com")
AttributeError: 'Vastaanottaja' object has no attribute '__tarkasta_sposti'
Samaa apumetodia kannattaa kutsua myös sähköpostia asettaessa - lisätään siis luokkaan esimerkin vuoksi havainnointi- ja asetusmetodit sähköpostille:
class Vastaanottaja:
def __init__(self, nimi: str, sposti: str):
self.__nimi = nimi
if self.__tarkasta_sposti(sposti):
self.__sposti = sposti
else:
raise ValueError("Sähköposti ei kelpaa")
def __tarkasta_sposti(self, sposti: str):
# Yksinkertainen tarkastus: osoitteessa on yli 5 merkkiä ja piste ja @-merkki
return len(sposti) > 5 and "." in sposti and "@" in sposti
@property
def sposti(self):
return self.__sposti
@sposti.setter
def sposti(self, sposti: str):
if self.__tarkasta_sposti(sposti):
self.__sposti = sposti
else:
raise ValueError("Sähköposti ei kelpaa")
Tarkastellaan sitten toista esimerkkiä. Luokka Korttipakka
mallintaa nimensä mukaisesti 52 kortin korttipakkaa. Apumetodi __alusta_pakka
luo uuden sekoitetun pakan oliota luotaessa. Vastaava alustus voitaisiin toki tehdä myös metodissa __init__
, mutta erillisen apumetodin käyttö tekee koodista siistimpää ja mahdollistaa alustusmetodin kutsumisen myös muualta luokasta tarvittaessa.
from random import shuffle
class Korttipakka:
def __init__(self):
self.__alusta_pakka()
def __alusta_pakka(self):
self.__pakka = []
# Laitetaan kaikki kortit pakkaan
maat = ["pata", "hertta", "risti", "ruutu"]
for maa in maat:
for numero in range(1, 14):
self.__pakka.append((maa, numero))
# Sekoitetaan pakka
shuffle(self.__pakka)
def jaa(self, korttien_maara: int):
kasi = []
# Siirretään pakasta ylimmät kortit käteen
for i in range(korttien_maara):
kasi.append(self.__pakka.pop())
return kasi
Seuraava koodi testaa luokkaa:
korttipakka = Korttipakka()
kasi1 = korttipakka.jaa(5)
print(kasi1)
kasi2 = korttipakka.jaa(5)
print(kasi2)
Ohjelma tulostaa esimerkiksi
[('pata', 7), ('pata', 11), ('hertta', 7), ('ruutu', 3), ('pata', 4)] [('risti', 8), ('pata', 12), ('ruutu', 13), ('risti', 11), ('pata', 10)]
Piilotettuja metodeja tarvitaan yleensä harvemmin kuin piilotettuja attribuutteja. Metodi kannattaa piilottaa, jos asiakas ei tarvitse siihen suoraa pääsyä, ja varsinkin silloin, jos on todennäköistä, että asiakas voisi sotkea olion sisäisen eheyden metodia kutsumalla.