Zoeken…


Invoering

Stel je voor dat je een klasse had met een paar behoorlijk belangrijke variabelen en dat deze (door andere programmeurs uit hun code) waren ingesteld op onacceptabele waarden. Hun code bracht fouten in je code. Als oplossing kunt u in OOP de status van een object (opgeslagen in zijn variabelen) alleen via methoden wijzigen. Het verbergen van de status van een object en het bieden van alle interactie via een objectmethode staat bekend als Data Encapsulation.

Opmerkingen

Het is veel eenvoudiger om te beginnen met het markeren van een variabele als private en deze zo nodig bloot te leggen dan een reeds public variabele te verbergen.

Er is één uitzondering waarbij inkapseling mogelijk niet nuttig is: "domme" gegevensstructuren (klassen met als enig doel variabelen vast te houden).

public class DumbData {
    public String name;
    public int timeStamp;
    public int value;
}

In dit geval is de interface van de klasse is de data die zij houdt.

Merk op dat variabelen die als final zijn gemarkeerd, public kunnen worden gemaakt zonder inkapseling te schenden, omdat ze niet kunnen worden gewijzigd nadat ze zijn ingesteld.

Inkapseling om invarianten te behouden

Er zijn twee delen van een klasse: de interface en de implementatie.

De interface is de zichtbare functionaliteit van de klasse. De openbare methoden en variabelen maken deel uit van de interface.

De implementatie is de interne werking van een klasse. Andere klassen hoeven niet op de hoogte te zijn van de implementatie van een klasse.

Inkapseling verwijst naar de praktijk om de implementatie van een klasse te verbergen voor alle gebruikers van die klasse. Hierdoor kan de klas aannames maken over zijn interne toestand.

Neem bijvoorbeeld deze klasse die een hoek vertegenwoordigt:

public class Angle {
    
    private double angleInDegrees;
    private double angleInRadians;
    
    public static Angle angleFromDegrees(double degrees){
        Angle a = new Angle();
        a.angleInDegrees = degrees;
        a.angleInRadians = Math.PI*degrees/180;
        return a;
    }
    
    public static Angle angleFromRadians(double radians){
        Angle a = new Angle();
        a.angleInRadians = radians;
        a.angleInDegrees = radians*180/Math.PI;
        return a;
    }
    
    public double getDegrees(){
        return angleInDegrees;
    }
    
    public double getRadians(){
        return angleInRadians;
    }
    
    public void setDegrees(double degrees){
        this.angleInDegrees = degrees;
        this.angleInRadians = Math.PI*degrees/180;
    }
    
    public void setRadians(double radians){
        this.angleInRadians = radians;
        this.angleInDegrees = radians*180/Math.PI;
    }
    private Angle(){}
}

Deze klasse is gebaseerd op een basisaanname (of invariant ): angleInDegrees en angleInRadians zijn altijd synchroon . Als de klasleden openbaar waren, zouden er geen garanties zijn dat de twee representaties van hoeken gecorreleerd zijn.

Inkapseling om koppeling te verminderen

Met inkapseling kunt u interne wijzigingen aanbrengen in een klasse zonder de code te beïnvloeden die de klasse aanroept. Dit vermindert de koppeling , of hoeveel een bepaalde klasse afhankelijk is van de implementatie van een andere klasse.

Laten we bijvoorbeeld de implementatie van de Angle-klasse van het vorige voorbeeld wijzigen:

public class Angle {
    
    private double angleInDegrees;
    
    public static Angle angleFromDegrees(double degrees){
        Angle a = new Angle();
        a.angleInDegrees = degrees;
        return a;
    }
    
    public static Angle angleFromRadians(double radians){
        Angle a = new Angle();
        a.angleInDegrees = radians*180/Math.PI;
        return a;
    }
    
    public double getDegrees(){
        return angleInDegrees;
    }
    
    public double getRadians(){
        return angleInDegrees*Math.PI / 180;
    }
    
    public void setDegrees(double degrees){
        this.angleInDegrees = degrees;
    }
    
    public void setRadians(double radians){
        this.angleInDegrees = radians*180/Math.PI;
    }

    private Angle(){}
}

De implementatie van deze klasse is gewijzigd, zodat deze slechts één weergave van de hoek opslaat en de andere hoek berekent wanneer dat nodig is.

De implementatie is echter veranderd, maar de interface niet . Als een oproepende klasse afhankelijk was van de toegang tot de methode angleInRadians, zou deze moeten worden gewijzigd om de nieuwe versie van Angle . Bellen naar klassen zou zich geen zorgen hoeven te maken over de interne weergave van een klas.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow