Геттеры и сеттеры
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 49 из 107.
Поскольку к неэкспортируемым полям нельзя получить прямой доступ извне package, необходимо предоставить методы, которые обеспечивают контролируемый доступ. Обычно их называют геттерами и сеттерами.
В Go соглашение для геттеров простое: используйте имя поля с заглавной первой буквой. Не добавляйте префикс «Get», просто используйте Balance(), а не GetBalance():
type BankAccount struct {
balance int // неэкспортируемый
}
// Геттер - возвращает значение
func (b *BankAccount) Balance() int {
return b.balance
}
// Сеттер - изменяет значение с валидацией
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
Настоящая сила сеттеров заключается в добавлении проверки или бизнес-логики. Вместо того чтобы позволять внешнему коду напрямую устанавливать любое значение, вы контролируете, что разрешено:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Этот метод Deposit действует как специализированный сеттер, который обеспечивает соблюдение правил: отрицательные депозиты не допускаются. Внешний код должен обращаться к вашим методам, благодаря чему структура всегда остаётся в допустимом состоянии. Это инкапсуляция в действии: данные скрыты, а контролируемое поведение предоставлено.
Задание
ЛегкоДавайте создадим конвертер температуры, демонстрирующий правильную инкапсуляцию с использованием методов getter и setter. Вы создадите структуру, которая хранит температуру внутри в Celsius, но предоставляет контролируемый доступ через методы с проверкой.
Вы организуете код в двух файлах:
temperature.go: Create структуруTemperatureс неэкспортируемым полемcelsius(float64). Implement следующие методы:Celsius()— getter, возвращающий current температуру в CelsiusSetCelsius(value float64)— setter, который принимает Only значения, равные absolute нулю или превышающие его (-273.15). Если значение ниже этого порога, температура должна остаться без изменений.Fahrenheit()— возвращает температуру, converted в Fahrenheit с использованием Formula:(celsius * 9/5) + 32SetFahrenheit(value float64)— converts input из Fahrenheit в Celsius и сохраняет его, но Only если resulting значение Celsius равно -273.15 или превышает его
NewTemperature(celsius float64) *Temperature, который creates температуру, initialized заданным значением (считайте input для constructor корректным).main.go: Считайте значения температуры из input и продемонстрируйте методы getter/setter. Create температуру, отобразите её значения в обеих единицах, затем попытайтесь установить новые значения и покажите resulting результаты.
Будут предоставлены следующие input:
- Строка 1: Initial значение Celsius
- Строка 2: Новое значение Celsius для установки
- Строка 3: Новое значение Fahrenheit для установки
Отформатируйте все значения температуры с двумя десятичными знаками. Print следующую последовательность:
- После создания:
C: [celsius] F: [fahrenheit] - После установки Celsius:
C: [celsius] F: [fahrenheit] - После установки Fahrenheit:
C: [celsius] F: [fahrenheit]
Например, если given значения 25, -300 и 212, ваш output должен быть:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Обратите внимание, что во второй строке показаны unchanged значения, потому что -300 ниже absolute нуля, поэтому setter отклонил это значение. В третьей строке показана температура после успешной установки 212°F (что converts в 100°C). В этом заключается сила setter. Они обеспечивают соблюдение правил, которые поддерживают корректность ваших данных.
Попробуйте сами
package main
import (
"fmt"
)
func main() {
// Прочитать входные значения
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Создать новый Temperature с помощью конструктора
// TODO: Вывести начальные значения в формате "C: [celsius] F: [fahrenheit]" с 2 знаками после запятой
// TODO: Попытаться установить новое значение Celsius и вывести результат
// TODO: Попытаться установить новое значение Fahrenheit и вывести результат
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker PoolПотренируйтесь самостоятельно: Онлайн-компилятор Go