Attribut
Aus 4webmaster.de
|
Attribute sind mit Daten beschreibbare Merkmale von Objekten. Da gleichartige Objekte die gleichen Attribute besitzen, werden diese in der Klasse des Objektes formuliert.
Die abstrakten Merkmale werden als Attribute bezeichnet (z.B. name und alter). Alle Attribute zusammengenommen bilden die Struktur des Objektes. In Java heißt ein Attribut field.
Die konkreten Eigenschaftsdaten heißen Attributwerte (z.B. "Sophie Meinerhoff" und 22). Alle Attributwerte zusammengenommen bilden den Zustand des Objektes.
Attribute lassen sich wie folgt charakterisieren:
| Name | Wie wird das Attribut identifiziert? |
| Typ | Was für Daten kann das Attribut aufnehmen? In Java haben Attribute einen festen Typ, z.B. int oder String. In Ruby haben dagegen nur die Attributwerte einen Typ. |
| Klassenattribut | oder normales Attribut (eines Objektes)? Nicht nur Objekte, sondern auch Klassen können Attribute haben. In Java werden diese Klassenattribute static fields genannt, in Ruby heißen sie class variables. |
| Sichtbarkeit | Wer kann auf die Daten des Attributes zugreifen? Jedes Attribut hat eine Sichtbarkeit, z.B. private oder public. Damit lässt sich eine Kapselung erreichen. |
| Standardwert | Wird dem Attribut ein Standardwert zugewiesen? Das Attribut wird damit zu einem optionalen Attribut. |
| Kardinalität | Wie viele Attribute dieses Namens hat das Objekt / die Klasse? Normalerweise ist die Kardinalität entweder 1 (required Attribut) oder 0..1 (optionales Attribut). Die Kardinalität wird auch Multiplizität oder Vielfachheit genannt. |
| Constraints | Constraints sind Gültigkeitsregeln / Zusicherungen: Welche Werte sind valide? Außerdem Sondereigenschaften wie z.B. read-only, ordered, etc. |
In Datenbanksystemen werden Attribute meist als Felder eines Datensatzes repräsentiert. Der Datensatz entspricht dann dem Objekt.
Darstellung von Attributen in UML
Attribute lassen sich in die Darstellung von Klassen und in die Darstellung von Objekten integrieren. Dazu werden die relevanten Attribute im zweiten Teil der Darstellung (zuständig für die Struktur der Klasse / des Objektes) eingetragen — komplett oder teilweise.
Notationsregeln
| Beispiel | angegeben wird | Erklärung |
|---|---|---|
| alter | Name | In der einfachsten Form wird nur der Name des Attributes angegeben. Der Name eines Attributes beginnt mit einem Kleinbuchstaben. |
| mindestalter | Name, ist Klassenattribut | Um Klassenattribute von Objektattributen unterscheiden zu können, werden Klassenattribute in UML unterstrichen dargestellt. |
| -alter | Sichtbarkeit, Name | Die Sichtbarkeit / Kapselung wird mit - # ~ + dargestellt. |
| alter:Integer | Name, Typ | Als Typen können UML-eigene Typen (Integer, Boolean, String) verwendet werden, aber auch Typen der Implementierungssprache (Double, Vector, Array, ...) oder Klassen. |
| alter:AlterInJahren | Name, Typ | Am besten aber gibt man eigene Typen an. Oft wird aus dem Typ später noch eine eigene Klasse gemacht, gerne auch mit eigener Repräsentation in der Datenbank... Dann sind sich alle Attributwerte Objekte einer anderen Klasse. Außerdem sind geeignete Namen für eigene Typen oft verständlicher! Das Alter könnte ja beispielsweise auch in Sekunden angegeben werden. |
| geschlecht:Geschlecht | Name, Typ | Noch ein Beispiel für einen selbstdefinierte Typ. Geschlecht sollte entweder als Aufzählungstyp (enumeration types) oder als eigene Klasse realisiert werden, keinesfalls als String. |
| alter:AlterInJahren = 18 | Name, Typ, Standardwert | Angabe eines default value. Das Attribut ist damit ein optionales Attribut. |
| alter:Alter[0..1] | Name, Typ, Kardinalität | Die Angabe der Kardinalität als 0..1 bedeutet, dass das Attribut keinmal oder genau einmal existieren darf. Das Attribut ist damit ein optionales Attribut. |
| vorname[1..∗] | Name, Typ, Kardinalität | Das Objekt kann beliebig viele Vornamens-Attribute haben, aber mindestens einen. Weitere Beispiele für die Angabe der Kardinalität:
1 ─▷ genau 1 (das ist der Standardwert) |
| telefon:Telefonnummer[2] = (+49, +49) | Name, Typ, Kardinalität, Standardwerte | Beispiel für das Setzen von zwei Standardwerten |
| /alter:AlterInJahren | Berechnetes Attribut, Name, Typ | Der Slash kennzeichnet das Attribut als virtuelles / berechnetes Attribut. |
Notationsregeln für Constraints
In geschweiften Klammern können Constraints für ein Attribut notiert werden. Constraints sind Einschränkungen, Zusicherungen, Gültigkeitsregeln, Randbedingungen oder besondere Eigenschaften. Sie beziehen sich auf die Menge von Objekten, die ein Attribut oder ein Assoziationsende liefert.
| Beispielnotation in UML | Bedeutung | Erklärung |
|---|---|---|
| alter:AlterInJahren {alter > 17, alter < 120} | Gültigkeitsregel | Gültigkeitsregeln / Zusicherungen werden als boolsche Ausdrücke notiert. |
| /alter:AlterInJahren {/alter = heutejahr - geburtsjahr} | Rechenweg | Hier wird der Rechenweg eines berechneten Attributes als Zusicherung angegeben. |
| alter{readOnly} | read-only | dieses Attribut ist read-only |
| treffer{ordered} | geordnet | Das Attribut liefert eine geordnete und eindeutige Liste von Objekten wie z.B. [ 2, 3, 4, 5 ] |
| treffer{bag} | geordnet | Das Attribut liefert eine ungeordnete und nicht-eindeutige Liste von Objekten wie z.B. [ 3, 3, 3, 1, 5 ] |
| treffer{sequence} | geordnet | Das Attribut liefert eine geordnete, aber nicht-eindeutige Liste von Objekten wie z.B. [ 2, 3, 3, 4 ] |
Fields in Java
In Java heißt ein Attribut field oder auch member variable. Um ein Attribut in Java fachgerecht zu verwenden, muss man
- es deklarieren (also Name, Typ und Sichtbarkeit festlegen, die Sichtbarkeit sollte private oder protected lauten)
- eine Getter-Methode erstellen, über die jeder Lesezugriff / jeder Lesezugriff von außen laufen sollte
- eine Setter-Methode erstellen, über die jeder Schreibzugriff / jeder Schreibzugriff von außen laufen sollte
Die Getter- und Setter-Methoden realisieren das Geheimnisprinzip, nach dem die Daten eines Objektes nur mit den Methoden des Objektes selbst gelesen und geschrieben werden können. Nach außen hin sind die Attributwerte dann unsichtbar. Nachteilig dabei ist, dass der Code durch solche Methoden aufgebläht wird (Zusatzarbeit entsteht indes kaum, da die Entwicklungsumgebungen die Methoden mit wenigen Klicks automatisch erstellen). Ein weiterer Nachteil ist, dass der Typ des Attributes redundant angegeben ist: Einmal in der Deklaration, und dann noch einmal als Rückgabetyp der Getter-Methode.
Beispiel:
public class Person { // Attributdeklarationen private String name; private int alter = 18; // mit Initialisierungswert private String adresse, email, mobil; // Mehrfachdeklaration // Getter und Setter public int getAlter() { return alter; } public void setAlter( int alter ) { // TODO: Plausibilitätsprüfung this.alter = alter; } // weitere Getter und Setter folgen }
In Java werden vom Konstruktor alle Attribute mit dem Wert null oder mit 0 initialisiert, wenn kein anderer Anfangswert vorgegeben ist.
In Java überdecken lokale Variabeln gleichnamige Attribute. Will man auf das Attribut zugreifen und nicht auf die lokale Variable, so schreibt man this. davor (Beispiel siehe obige Setter-Methode). Das entspricht einem Direktzugriff auf das Attribut, genauso wie beispielsweise person1.alter.
Static Fields in Java
Nicht nur Objekte, sondern auch Klassen können Attribute haben. In Java werden diese Klassenattribute static fields oder auch class variables genannt.
private static int mindestalter;
Die Setter und Getter sehen genauso aus wie bei normalen Attributen, werden aber als statische Methoden (Klassenmethoden) realisiert. Beim Zugriff wird die Klasse wie ein Objekt behandelt, d.h.
Person.mindestalter
liefert den Wert des gewünschten Klassenattribut.
In Java ist es auch möglich, auf die Klassenattribute über ein ein beliebiges Objekt zuzugreifen:
irgendeineperson.mindestalter
liefert den gleichen Wert. Deswegen heißen Klassenattribute in Java auch static: Sie sind einfach für alle Objekte einer Klasse identisch.
Instanzvariablen und Attribute in Ruby
In Ruby wird zwischen Attributen und Instanzvariablen unterschieden: Instanzvariablen sind die (privaten) Variablen eines Objektes. Attribute sind "nach außen sichtbare Instanzvariablen", genauer: ganz normale Getter- und Setter-Methoden, mit denen Instanzvariablen nach außen sichtbar gemacht werden können.
Die Namen von Instanzvariablen beginnen stets mit dem @-Zeichen. Die Getter-Methode für die Instanzvariable @name lautet standardmäßig name, ihre Setter-Methode lautet name= . Dadurch kann man sehr elegant auf die Instanzvariablen zugreifen und sie als Attribute verwenden:
julia = Person.new julia.alter = 44 puts julia.alter // gibt 44 aus
Instanzvariablen sind private für eine Klasse und ihre Objekte, will man von außen auf sie zugreifen, so muss man Getter- und Setter-Methoden schreiben. Diese können entweder manuell geschrieben werden oder über eine Klassenmethode dynamisch erzeugt werden: Die Klassenmethode attr_accessor nimmt Attributnamen (als Ruby-Symbol oder als Liste von Ruby-Symbolen) als Parameter an und erzeugt die gewünschten Getter- und Setter-Methoden.
Beispiel:
class Person // Setter- und Getter-Methoden für @name und @alter erzeugen attr_accessor :name, :alter // Anfangswerte setzen def initialize // @name ist standardmäßig nil @alter = 18 end end
Variablen (also auch Instanzvariablen) müssen in Ruby nicht deklariert werden. Außerdem ist der Typ nicht festgelegt und kann zur Laufzeit jederzeit variieren. Dadurch haben Attribute in Ruby keinen festen Typ.
Klassenvariablen in Ruby
Auch in Ruby gibt es Attribute, die von allen Objekten einer Klasse geteilt werden. Sie heißen class variables und werden mit zwei @-Zeichen notiert:
class Person @@mindestalter = 18 end
Anders als Instanzvariablen müssen Klassenvariablen vor der Verwendung initialisiert werden. Sie sind private für eine Klasse, will man von außen auf sie zugreifen, so muss man Getter- und Setter-Methoden schreiben.
Siehe auch