Getter- und Setter-Methoden
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 49 von 107.
Da auf nicht exportierte Felder nicht direkt von außerhalb eines Pakets zugegriffen werden kann, musst du Methoden bereitstellen, die einen kontrollierten Zugriff ermöglichen. Diese werden üblicherweise Getter und Setter genannt.
In Go ist die Konvention für Getter einfach: Verwende den field-Namen mit einem Großbuchstaben am Anfang. Setze nicht „Get“ voran, sondern verwende einfach Balance(), nicht GetBalance():
type BankAccount struct {
balance int // nicht exportiert
}
// Getter - gibt den Wert zurück
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - ändert den Wert mit Validierung
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
Die wahre Stärke von Settern liegt darin, Validierung oder Geschäftslogik hinzuzufügen. Anstatt externem Code zu erlauben, direkt jeden beliebigen Wert zu setzen, kontrollierst du, was zulässig ist:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Diese Deposit-Methode fungiert als spezialisierter Setter, der Regeln durchsetzt: keine negativen Einzahlungen erlaubt. Externer Code muss deine Methoden verwenden, sodass die Struktur stets in einem gültigen Zustand bleibt. Das ist Kapselung in Aktion: Die Daten werden verborgen, während ein kontrolliertes Verhalten bereitgestellt wird.
Aufgabe
EinfachWir erstellen einen Temperaturkonverter, der die ordnungsgemäße Kapselung mithilfe von Getter- und Setter-Methoden demonstriert. Du erstellst eine Struktur, die die Temperatur intern in Celsius speichert, aber über Methoden mit Validierung einen kontrollierten Zugriff ermöglicht.
Du organisierst deinen Code auf zwei Dateien verteilt:
temperature.go: Erstelle eineTemperature-Struktur mit einem nicht exportierten Feldcelsius(float64). Implementiere die folgenden Methoden:Celsius()– ein Getter, der die aktuelle Temperatur in Celsius zurückgibtSetCelsius(value float64)– ein Setter, der nur Werte ab dem absoluten Nullpunkt (-273.15) akzeptiert. Wenn der Wert unter diesem Grenzwert liegt, soll die Temperatur unverändert bleiben.Fahrenheit()– gibt die in Fahrenheit umgerechnete Temperatur mithilfe der Formel(celsius * 9/5) + 32zurückSetFahrenheit(value float64)– rechnet die Eingabe von Fahrenheit in Celsius um und speichert sie, aber nur, wenn der resultierende Celsius-Wert mindestens -273.15 beträgt
NewTemperature(celsius float64) *Temperaturehinzu, der eine auf den angegebenen Wert initialisierte Temperatur erstellt (für den Konstruktor kannst du von einer gültigen Eingabe ausgehen).main.go: Lies Temperaturwerte aus der Eingabe ein und demonstriere die Getter-/Setter-Methoden. Erstelle eine Temperatur, zeige ihre Werte in beiden Einheiten an, versuche anschließend, neue Werte zu setzen, und zeige die Ergebnisse.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Anfangswert in Celsius
- Zeile 2: Neuer zu setzender Celsius-Wert
- Zeile 3: Neuer zu setzender Fahrenheit-Wert
Formatiere alle Temperaturausgaben mit zwei Dezimalstellen. Gib die folgende Reihenfolge aus:
- Nach der Erstellung:
C: [celsius] F: [fahrenheit] - Nach dem Setzen von Celsius:
C: [celsius] F: [fahrenheit] - Nach dem Setzen von Fahrenheit:
C: [celsius] F: [fahrenheit]
Wenn beispielsweise 25, -300 und 212 gegeben sind, sollte deine Ausgabe wie folgt aussehen:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Beachte, dass die zweite Zeile unveränderte Werte zeigt, weil -300 unter dem absoluten Nullpunkt liegt und der Setter den Wert daher abgelehnt hat. Die dritte Zeile zeigt die Temperatur nach dem erfolgreichen Setzen von 212 °F (was in 100 °C umgerechnet wird). Das ist die Stärke von Settern: Sie setzen Regeln durch, die deine Daten gültig halten.
Probier es selbst
package main
import (
"fmt"
)
func main() {
// Eingabewerte lesen
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Erstelle eine neue Temperature mit dem Konstruktor
// TODO: Gib die Anfangswerte im Format "C: [celsius] F: [fahrenheit]" mit 2 Dezimalstellen aus
// TODO: Versuche, den neuen Celsius-Wert zu setzen und das Ergebnis auszugeben
// TODO: Versuche, den neuen Fahrenheit-Wert zu setzen und das Ergebnis auszugeben
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP in Go
Externe DateienGo-Workspace & ModulePackages & ImportsExportierte vs. nicht exportierte NamenEinführung in OOP mit GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktorfunktionenRückblick – Einfacher Taschenrechner4Schnittstellen
Einführung in SchnittstellenImplizite ImplementierungSchnittstelle als VertragLeere Schnittstelle (any)TypzusicherungTypwechselZusammensetzung von SchnittstellenStringer- und Error-SchnittstellenRückblick – Formenrechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf PaketebeneGetter- und Setter-MethodenInformationsverbergung in GoRückblick – Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterTypbeschränkungenGenerische StrukturenWorkaround für generische MethodenZusammenfassung – Generische Sammlung2Typen & Structs im Detail
Grundlegende & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct-TagsAnonyme StructsVerschachtelte StructsNullwerte & StandardwerteRückblick – Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen der Struct-EinbettungMethoden-PromotionMehrere Structs einbettenEinbettung vs. AggregationVerbergen eingebetteter MethodenRückblick – Mitarbeiterhierarchie8Fehlerbehandlung & OOP
Das Error-InterfaceBenutzerdefinierte FehlertypenError-Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverRückblick – Dateiparser3Zeiger & Speicher
Grundlagen von Zeigern in GoZeiger auf StructsÜbergabe per Wert vs. ReferenzDie Funktion new()Garbage Collection in GoRückblick – Verkettete Liste erstellen6Polymorphismus in Go
Polymorphismus über InterfacesDuck-Typing in GoRegeln zur Interface-ErfüllungPolymorphe SammlungenDependency InjectionZusammenfassung – Zahlungsprozessor9Konkurrenz & OOP
Grundlagen der GoroutinesChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignRückblick – Worker PoolÜbe selbstständig: Online-Go-Compiler