L'encapsulació és un dels quatre pilars de la programació orientada a objectes (POO), juntament amb l'herència, el polimorfisme i l'abstracció. En termes simples, l'encapsulació és el procés de 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. Visibilitat dels Membres:

    • Privat (private): Només accessible dins de la mateixa classe.
    • Protegit (protected): Accessible dins de la mateixa classe i subclasses.
    • Públic (public): Accessible des de qualsevol lloc.
    • Paquet (package-private): Accessible dins del mateix paquet (per defecte, sense modificador).
  2. Getters i Setters:

    • Mètodes públics que permeten accedir i modificar els atributs privats d'una classe.
  3. Beneficis de l'Encapsulació:

    • Control d'Accés: Permet controlar com es modifiquen els atributs.
    • Modularitat: Facilita la divisió del codi en mòduls més petits i manejables.
    • Mantenibilitat: Fa que el codi sigui més fàcil de mantenir i actualitzar.
    • Protecció de Dades: Evita que dades crítiques siguin modificades de manera inadequada.

Exemple Pràctic

A continuació, es mostra un exemple pràctic d'encapsulació en Groovy:

class Persona {
    private String nom
    private int edat

    // Constructor
    Persona(String nom, int edat) {
        this.nom = nom
        this.edat = edat
    }

    // Getter per a nom
    String getNom() {
        return nom
    }

    // Setter per a nom
    void setNom(String nom) {
        this.nom = nom
    }

    // Getter per a edat
    int getEdat() {
        return edat
    }

    // Setter per a edat
    void setEdat(int edat) {
        if (edat > 0) {
            this.edat = edat
        } else {
            println "L'edat ha de ser un valor positiu."
        }
    }
}

// Ús de la classe Persona
def persona = new Persona("Joan", 30)
println persona.getNom()  // Joan
println persona.getEdat() // 30

persona.setNom("Anna")
persona.setEdat(25)
println persona.getNom()  // Anna
println persona.getEdat() // 25

persona.setEdat(-5) // L'edat ha de ser un valor positiu.

Explicació del Codi

  1. Definició de la Classe:

    • La classe Persona té dos atributs privats: nom i edat.
    • El constructor inicialitza aquests atributs.
  2. Getters i Setters:

    • Els mètodes getNom i getEdat permeten accedir als atributs privats.
    • Els mètodes setNom i setEdat permeten modificar els atributs privats. El setter per a edat inclou una validació per assegurar-se que l'edat sigui un valor positiu.
  3. Ús de la Classe:

    • Es crea una instància de la classe Persona i es mostren els valors inicials dels atributs.
    • Es modifiquen els atributs utilitzant els setters i es mostren els nous valors.
    • Es prova de modificar l'edat amb un valor negatiu, i es mostra un missatge d'error.

Exercicis Pràctics

Exercici 1: Crear una Classe amb Encapsulació

Crea una classe CompteBancari amb els següents atributs privats: numeroCompte, saldo. Implementa getters i setters per aquests atributs, assegurant-te que el saldo no pugui ser negatiu.

Solució

class CompteBancari {
    private String numeroCompte
    private double saldo

    // Constructor
    CompteBancari(String numeroCompte, double saldo) {
        this.numeroCompte = numeroCompte
        this.saldo = saldo >= 0 ? saldo : 0
    }

    // Getter per a numeroCompte
    String getNumeroCompte() {
        return numeroCompte
    }

    // Setter per a numeroCompte
    void setNumeroCompte(String numeroCompte) {
        this.numeroCompte = numeroCompte
    }

    // Getter per a saldo
    double getSaldo() {
        return saldo
    }

    // Setter per a saldo
    void setSaldo(double saldo) {
        if (saldo >= 0) {
            this.saldo = saldo
        } else {
            println "El saldo no pot ser negatiu."
        }
    }
}

// Ús de la classe CompteBancari
def compte = new CompteBancari("123456789", 1000.0)
println compte.getNumeroCompte()  // 123456789
println compte.getSaldo()         // 1000.0

compte.setSaldo(500.0)
println compte.getSaldo()         // 500.0

compte.setSaldo(-100.0)           // El saldo no pot ser negatiu.

Exercici 2: Afegir Mètodes per a Operacions

Afegeix mètodes a la classe CompteBancari per a dipositar i retirar diners. Assegura't que no es pugui retirar més diners dels que hi ha al compte.

Solució

class CompteBancari {
    private String numeroCompte
    private double saldo

    // Constructor
    CompteBancari(String numeroCompte, double saldo) {
        this.numeroCompte = numeroCompte
        this.saldo = saldo >= 0 ? saldo : 0
    }

    // Getter per a numeroCompte
    String getNumeroCompte() {
        return numeroCompte
    }

    // Setter per a numeroCompte
    void setNumeroCompte(String numeroCompte) {
        this.numeroCompte = numeroCompte
    }

    // Getter per a saldo
    double getSaldo() {
        return saldo
    }

    // Setter per a saldo
    void setSaldo(double saldo) {
        if (saldo >= 0) {
            this.saldo = saldo
        } else {
            println "El saldo no pot ser negatiu."
        }
    }

    // Mètode per a dipositar diners
    void dipositar(double quantitat) {
        if (quantitat > 0) {
            saldo += quantitat
        } else {
            println "La quantitat a dipositar ha de ser positiva."
        }
    }

    // Mètode per a retirar diners
    void retirar(double quantitat) {
        if (quantitat > 0 && quantitat <= saldo) {
            saldo -= quantitat
        } else {
            println "Quantitat no vàlida per a retirar."
        }
    }
}

// Ús de la classe CompteBancari
def compte = new CompteBancari("123456789", 1000.0)
println compte.getSaldo()         // 1000.0

compte.dipositar(200.0)
println compte.getSaldo()         // 1200.0

compte.retirar(300.0)
println compte.getSaldo()         // 900.0

compte.retirar(1000.0)            // Quantitat no vàlida per a retirar.

Resum

L'encapsulació és una tècnica fonamental en la programació orientada a objectes que ajuda a protegir les dades i a mantenir el codi organitzat. Utilitzant modificadors d'accés i mètodes getters i setters, podem controlar com es modifiquen i accedeixen els atributs d'una classe. Aquesta pràctica no només millora la seguretat del codi, sinó que també facilita la seva mantenibilitat i extensibilitat.

© Copyright 2024. Tots els drets reservats