Checkmark on Circle.png

Datenkapselung

Aus KGS-Wiki

Datenkapselung ist ein Konzept aus der objektorientierten Programmierung. Die Idee ist, dass Objekte ihre Attribute nicht öffentlich zur Verfügung stellen sollten. Stattdessen stellen die Objekte Schnittstellen zur Verfügung, um den Zugriff auf diese Attribute kontrollieren zu können.

Damit behalten Objekte selbst die Kontrolle über ihre Daten und definieren selbst, wer welchen Zugriff darauf haben kann. Damit kann z.B. eine Autorisierung eingefordert werden oder verhindert werden, dass zwei parallel laufende Threads gleichzeitig ein Objekt verändern (Race condition). Auch unsinnige Eingabewerte können so verhindert werden.

Der Zugriff auf diese Attribute erfolgt über Methoden, deren Namen typischerweise mit get oder set beginnen und die darum Getter und Setter genannt werden. Dies ist aber keinesfalls vorgeschrieben, der Zugriff kann auch anderweitig eingeschränkt werden.

Beispiele

Brüche in Python

Das folgende Beispiel zeigt eine Python-Klasse für Brüche. Jedes Fraction-Objekt hat zwei Attribute: numerator (Zähler) und denominator (Nenner). Hier ist es sinnvoll, den Zugriff auf den Nenner zu beschränken, damit dieser nicht auf 0 gesetzt werden kann, weil eine Division durch 0 mathematisch nicht zulässig ist.

class Fraction:

	def __init__(self, numerator, denominator):
        if type(numerator) != int or type(denominator) != int:
            raise Exception('Zähler und Nenner müssen ganze Zahlen sein!')
        if denominator == 0:
            raise Exception('Der Nenner darf nicht 0 sein!')
        self.__numerator = numerator
        self.__denominator = denominator

	def get_numerator(self):
		return self.__numerator

	def set_numerator(self, numerator):
        if type(numerator) != int:
            raise Exception('Der Zähler muss eine ganze Zahl sein!')
        self.__numerator = numerator

	def get_denominator(self):
		return self.__denominator

	def set_denominator(self, denominator):
        if type(denominator) != int:
            raise Exception('Der Nenner muss eine ganze Zahl sein!')
        if denominator == 0:
            raise Exception('Der Nenner darf nicht 0 sein!')
        self.__denominator = denominator

Folgendermaßen wird die Datenkapselung in dieser Klasse umgesetzt:

  • Diese Klasse hat zwei Attribute: __numerator und __denominator (Z. 8, 9).
  • Durch die führenden __ wird die Sichtbarkeit der Variablen auf private gesetzt.
  • Der Zugriff ist nur über die Methoden get_numerator (Z. 11), set_numerator (Z. 14), get_denominator (Z. 19) und set_denominator (Z. 22) möglich.
  • Die Setter überprüfen dabei, ob die übergebenen Parameter auch wirklich ganze Zahlen sind und erzeugen eine Exception, falls dies nicht der Fall ist (Z. 16, 24).
  • set_denominator stellt außerdem sicher, dass der Nenner nicht auf 0 gesetzt wird, da dies mathematisch nicht möglich ist (Z. 26).

Konten in Java

Das folgende Beispiel zeigt eine Java-Klasse für Bankkonten mit einem angedeuteten Sicherheitsmechanismus in Form einer PIN. Hier wird das Attribut amount (Kontostand) durch eine PIN-Abfrage geschützt und die Veränderung des Kontostandes nur durch spezielle Methoden erlaubt.

public class BankAccount {

    private double amount;
    private int pin;

    public BankAccount(int pin) {
        this.amount = 0;
        this.pin = pin;
    }

    public double getAmount(int pin) throws WrongPinException{
        if (this.pin != pin) {
            throw new WrongPinException();
        }
        return amount;
    }

    public void deposit(double amountToDeposit) {
        this.amount = this.amount + amountToDeposit;
    }

    public void withdraw(int pin, double amountToWithdraw) throws YouAreBrokeException, WrongPinException {
        if (this.pin != pin) {
            throw new WrongPinException();
        }
        if (this.amount < amountToWithdraw) {
            throw new YouAreBrokeException();
        }
        this.amount = this.amount - amountToWithdraw;
    }

    public void setPin(int newPin) {
        this.pin = newPin;
    }
}
  • In Java wird die Sichtbarkeit der Attribute mit dem Schlüsselwort private eingeschränkt (Z. 3, 4).
  • Hier gibt es statt eines Setters zwei Methoden deposit (Z. 18) und withdraw (Z. 22), mit denen der Kontostand um eine gewisse Summe verändert werden kann.
  • Die Getter und Setter prüfen hier als primitive Sicherheitskontrolle, ob eine übergebene pin mit der gespeicherten pin übereinstimmt (Z. 12, 23), und zusätzlich beim Abheben, ob genug Geld auf dem Konto vorhanden ist (Z. 26). Ansonsten werden auch hier Exceptions produziert (Z. 13, 24, 27).
  • Die pin kann zwar geändert werden (setPin in Z. 32–34), aber aus Sicherheitsgründen nicht abgefragt werden.