Как в Go встраивание заменяет наследование
Что проверяют
Понимаете ли вы, что встраивание даёт переиспользование кода, но не отношение «является». Следом обычно спрашивают, как тогда в Go получить полиморфизм и что будет, если внешний тип определит метод с тем же именем.
Как отвечать
Встраивание это поле без имени: type Admin struct { User; Level int }. Поля и методы User продвигаются наверх и доступны как admin.Name и admin.Greet(). Под капотом это обычная композиция, компилятор подставляет admin.User.Greet().
Чем это отличается от наследования:
- нет подтипа:
Adminне являетсяUser, передать его туда, где ждутUser, нельзя. Полиморфизм в Go даётся интерфейсами: еслиAdminчерез продвижение получил все методы интерфейса, он этот интерфейс реализует; - нет виртуальной диспетчеризации: если
User.Greetвызываетu.Title(), аAdminопределил свойTitle, вызовется версияUser. «Шаблонный метод» через встраивание не работает, получатель внутри метода всегдаUser; - затенение: метод внешнего типа с тем же именем скрывает встроенный, до исходного можно достучаться явно,
admin.User.Greet(). Два одинаковых имени на одной глубине дают ошибку компиляции только при обращении к ним; - наборы методов: при встраивании
Tметоды с получателем*Tвходят только в набор*Admin, это важно для реализации интерфейсов. Встраивание*Tпродвигает все методы.
Где встраивание уместно: собрать интерфейс из маленьких (io.ReadWriter из io.Reader и io.Writer) или обернуть чужой тип и переопределить один метод, например обёртка над http.ResponseWriter в middleware, которая запоминает код ответа.
Где спотыкаются
Говорят «Admin наследует User» и ждут переопределения, как в Java. На вопросе про вызов метода изнутри встроенного типа такой ответ разваливается.
Встраивают sync.Mutex в экспортируемую структуру. Lock и Unlock становятся частью её публичного API, а копирование структуры по значению копирует и мьютекс, что ловит go vet.
Встраивают интерфейс в структуру и забывают, что по умолчанию он nil. Вызов нереализованного метода компилируется, но падает с паникой в рантайме.