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

  1. Atributs Privats: Atributs que no es poden accedir directament des de fora de la classe.
  2. Mètodes Accessors: Mètodes que permeten accedir als atributs privats.
  3. Mètodes Mutadors: Mètodes que permeten modificar els atributs privats.
  4. 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

Mòdul 2: Estructures de Control

Mòdul 3: Funcions i Mòduls

Mòdul 4: Estructures de Dades

Mòdul 5: Programació Orientada a Objectes

Mòdul 6: Gestió de Fitxers

Mòdul 7: Gestió d'Errors i Excepcions

Mòdul 8: Temes Avançats

Mòdul 9: Proves i Depuració

Mòdul 10: Desenvolupament Web amb Python

Mòdul 11: Ciència de Dades amb Python

Mòdul 12: Projecte Final

© Copyright 2024. Tots els drets reservats