In der objektorientierten Programmierung gilt es als fortschrittlich, getter und setter zu verwenden, statt auf Attribute direkt zuzugreifen, weil das einem die Flexibilität gibt, später auf berechnete Attribute umzuschwenken. Etwas hässlich ist das, weil die getter und setter, etwas willkürlich den Attributnamen mit so einem vorangestellten „get“ oder „is“ oder „set“ und eventueller Umwandlung der Groß- und Kleinschreibung einzelner Zeichen versehen. Eine subtile Besonderheit ist, dass es verwirrend wird, wenn Attributnamen mit „get“, „is“ oder „set“ beginnen. Gerade Boolean-Attribute ist man versucht mit „hasSomething“, „isSomething“, „doesSomething“, „canSomething“, „mustSomething“,… o.ä. zu benennen, was dann zu dem Getter „getIsSomething()“ oder „isIsSomething()“ führt. Oder man lässt in dem Fall das Präfix weg, aber nur beim Getter…
Schöner ist es, wenn man Getter und Setter natürlich bennen kann, wie das z.B. in C#, Ruby und Scala der Fall ist: Man schreibt den Getter so, als würde man das Attribut public machen und darauf zugreifen, aber hat durch die entsprechenden Sprachkonstrukte die Möglichkeit, die Getter und Setter durch andere Implementierungen zu ersetzen, wenn der Bedarf besteht. Es gibt sicher wichtigeres, aber das ist zumindest schöner, lesbarer und deshalb weniger fehleranfällig. Und sprachlich auch sauberer als diese „halb-magic“-Bedeutung von „get…“, „set…“ und „is…“.
Im Grunde genommen sind aber auch Zugriffe auf Listen und Maps oft eine Art Getter und Setter:
y=a.get(pos)
könnte man auch als y=a[pos]
schreiben wollen, entsprechend a.put(pos, x)
auch als a[pos]=x
. Dasselbe gilt für Maps mit u=m.get(k)
, was schöner und intuitiver als etwas in der Art von u=m[k]
wäre. Oder statt m.put(k, v)
so etwas wie m[k]=v
. Aus genügend abstrakter Sicht ist das nicht so wichtig, aber wenn die Lesbarkeit sich verbessert, macht man weniger Fehler und so hat man pragmatisch gesehen einen kleinen Qualitäts und Effizienzgewinn mit der Zuweisungsschreibweise.
Nun sind aber Setter in Wirklichkeit oft problematisch. Es ist immer gut, Objekte immutable zu haben, weil man sie dann problemloser zwischen Threads herumreichen kann, ohne dass es zu Fehler bei gleichzeitigen Zugriffen kommen kann. Nun stellt sich aber die Frage, wie man dann das Objekt konstruieren soll. Ein Konstruktor mit positionalen Parametern ist zwar möglich, aber oft nicht sehr lesbar, wenn die Parameterliste nicht völlig überschaubar und klar ist. So etwas wie benannte Parameter könnte sehr viel helfen. Ein anderes Muster ist es, ein temporäres Objekt mit Settern aufzubauen und dann daraus das eigenteliche unveränderliche (immutable) Objekt zu generieren. Man kann dafür spezielle Setter nehmen, die jeweils das veränderte Objekt zurückgeben und das etwa so etwas schreiben wie
SomethingImmutable s = new SomethingTemp().setX(x).setY(y).setZ(z).toSomething()
,
was nicht superschön ist, aber wenn man auf Java Wert legt, doch eine Möglichkeit.
Hier zeigt sich auch, warum es so schön ist, wenn man Listen und Maps und vielleicht andere Collections einfach mit allen Elementen konstruieren und dann gleich immutable machen kann. In Java geht das für Listen immerhin schon mit
Collections.immutableList(Arrays.asList(a, b, c, d, e, f, g, h))
machen. Wobei diese Konstruktion relativ neu ist und wegen der Konstruktionsphase Collections nicht defaultmäßig immutable sein können. Immerhin könnte man ein
Arrays.asImmutableList(T..t)
definieren. Oder eine Methode auf List
.immutable()
.
Schöner (klarer, lesbarer, weniger fehleranfällig) wäre es aber, wenn man das als
[a, b, c, d, e, f, g, h]
schreiben könnte. Für die Ausgabe von Listen mittels toString()
wird so etwas ja schon verstanden. Für das Konstruieren von Maps gibt es in anderen Programmiersprachen auch Schreibweisen, die etwa so aussehen wie
m = { k1 => v1, k2 => v2, k3 => v3, k4 => v4}
.
Will man sich normalerweise dafür interessieren, welche Map-Implementierung jetzt genommen wird? So etwas ließe sich als
m = new TreeMap{k1 => v1, k2 => v2, k3 => v3, k4 => v4}
schreiben. Solche Dinge waren für Java 8 vorgesehen, sind aber wohl in letzter Minute rausgeflogen oder auf Java 9 verschoben worden.