L'encapsulació és un dels quatre pilars de la programació orientada a objectes (POO), juntament amb l'herència, el polimorfisme i l'abstracció. L'encapsulació consisteix a restringir l'accés a certs components d'un objecte i només permetre la seva modificació a través de mètodes específics. Això ajuda a protegir la integritat de les dades i a mantenir el codi més organitzat i fàcil de mantenir.
Conceptes Clau
- Atributs Privats: Atributs que no es poden accedir directament des de fora de la classe.
- Mètodes Accessors: Mètodes que permeten accedir als atributs privats.
- Mètodes Mutadors: Mètodes que permeten modificar els atributs privats.
- Propietats: Una manera més elegant i Pythonica d'accedir i modificar els atributs privats.
Atributs Privats
En Python, els atributs privats es defineixen prefixant el nom de l'atribut amb dos guions baixos (__
). Això no impedeix completament l'accés a l'atribut, però fa que sigui més difícil accedir-hi accidentalment.
class Persona: def __init__(self, nom, edat): self.__nom = nom self.__edat = edat def mostrar_informacio(self): print(f"Nom: {self.__nom}, Edat: {self.__edat}") persona = Persona("Joan", 30) # persona.__nom # Això donarà un error persona.mostrar_informacio() # Això funciona correctament
Mètodes Accessors i Mutadors
Els mètodes accessors (getters) i mutadors (setters) permeten accedir i modificar els atributs privats de manera controlada.
class Persona: def __init__(self, nom, edat): self.__nom = nom self.__edat = edat def get_nom(self): return self.__nom def set_nom(self, nom): self.__nom = nom def get_edat(self): return self.__edat def set_edat(self, edat): if edat > 0: self.__edat = edat else: print("L'edat ha de ser un valor positiu") persona = Persona("Joan", 30) print(persona.get_nom()) # Joan persona.set_edat(35) print(persona.get_edat()) # 35
Propietats
Les propietats en Python permeten definir mètodes accessors i mutadors d'una manera més elegant utilitzant el decorador @property
.
class Persona: def __init__(self, nom, edat): self.__nom = nom self.__edat = edat @property def nom(self): return self.__nom @nom.setter def nom(self, nom): self.__nom = nom @property def edat(self): return self.__edat @edat.setter def edat(self, edat): if edat > 0: self.__edat = edat else: print("L'edat ha de ser un valor positiu") persona = Persona("Joan", 30) print(persona.nom) # Joan persona.edat = 35 print(persona.edat) # 35
Exercicis Pràctics
Exercici 1
Crea una classe CompteBancari
amb els següents atributs privats: titular
, saldo
. Defineix mètodes accessors i mutadors per aquests atributs, assegurant-te que el saldo no pugui ser negatiu.
Solució
class CompteBancari: def __init__(self, titular, saldo): self.__titular = titular self.__saldo = saldo @property def titular(self): return self.__titular @titular.setter def titular(self, titular): self.__titular = titular @property def saldo(self): return self.__saldo @saldo.setter def saldo(self, saldo): if saldo >= 0: self.__saldo = saldo else: print("El saldo no pot ser negatiu") # Prova compte = CompteBancari("Anna", 1000) print(compte.titular) # Anna print(compte.saldo) # 1000 compte.saldo = 500 print(compte.saldo) # 500 compte.saldo = -100 # El saldo no pot ser negatiu
Exercici 2
Crea una classe Rectangle
amb atributs privats ample
i alt
. Defineix mètodes per calcular l'àrea i el perímetre del rectangle. Utilitza propietats per accedir i modificar els atributs.
Solució
class Rectangle: def __init__(self, ample, alt): self.__ample = ample self.__alt = alt @property def ample(self): return self.__ample @ample.setter def ample(self, ample): if ample > 0: self.__ample = ample else: print("L'ample ha de ser un valor positiu") @property def alt(self): return self.__alt @alt.setter def alt(self, alt): if alt > 0: self.__alt = alt else: print("L'alt ha de ser un valor positiu") def area(self): return self.__ample * self.__alt def perimetre(self): return 2 * (self.__ample + self.__alt) # Prova rectangle = Rectangle(5, 10) print(rectangle.area()) # 50 print(rectangle.perimetre()) # 30 rectangle.ample = 7 print(rectangle.area()) # 70
Conclusió
L'encapsulació és una tècnica fonamental en la programació orientada a objectes que ajuda a protegir les dades i a mantenir el codi més organitzat. Utilitzant atributs privats, mètodes accessors i mutadors, i propietats, podem controlar l'accés i la modificació dels atributs d'una classe de manera segura i eficient.
Curs de Programació en Python
Mòdul 1: Introducció a Python
- Introducció a Python
- Configuració de l'Entorn de Desenvolupament
- Sintaxi de Python i Tipus de Dades Bàsics
- Variables i Constants
- Entrada i Sortida Bàsiques
Mòdul 2: Estructures de Control
Mòdul 3: Funcions i Mòduls
- Definició de Funcions
- Arguments de Funció
- Funcions Lambda
- Mòduls i Paquets
- Visió General de la Biblioteca Estàndard
Mòdul 4: Estructures de Dades
Mòdul 5: Programació Orientada a Objectes
Mòdul 6: Gestió de Fitxers
- Lectura i Escriptura de Fitxers
- Treballant amb Fitxers CSV
- Gestió de Dades JSON
- Operacions amb Fitxers i Directoris
Mòdul 7: Gestió d'Errors i Excepcions
Mòdul 8: Temes Avançats
- Decoradors
- Generadors
- Gestors de Context
- Concurrència: Fils i Processos
- Asyncio per a Programació Asíncrona
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb unittest
- Desenvolupament Guiat per Proves
- Tècniques de Depuració
- Ús de pdb per a la Depuració
Mòdul 10: Desenvolupament Web amb Python
- Introducció al Desenvolupament Web
- Conceptes Bàsics del Framework Flask
- Construcció d'APIs REST amb Flask
- Introducció a Django
- Construcció d'Aplicacions Web amb Django
Mòdul 11: Ciència de Dades amb Python
- Introducció a la Ciència de Dades
- NumPy per al Càlcul Numèric
- Pandas per a la Manipulació de Dades
- Matplotlib per a la Visualització de Dades
- Introducció al Machine Learning amb scikit-learn