Какие базовые принципы ООП: абстракция, наследование, инкапсуляция, полиморфизм
Что проверяют
Понимаете ли вы, что Go не объектно-ориентированный язык в классическом смысле: классов и наследования в нём нет, а четыре принципа выражаются другими средствами. Следом почти всегда спрашивают, чем встраивание отличается от наследования и как в Go устроены интерфейсы.
Как отвечать
Сначала коротко дайте определение, потом покажите, чем каждый принцип выражен в Go:
- абстракция: выделение существенного поведения и сокрытие деталей. В Go это интерфейсы, и чем они меньше, тем лучше:
io.Readerс одним методомReadописывает и файл, и сетевое соединение, и буфер в памяти; - инкапсуляция: объект сам охраняет свои инварианты. Видимость в Go задаётся регистром первой буквы и работает на уровне пакета, а не типа: неэкспортируемое поле
balanceдоступно любому коду в том же пакете. Поэтому инварианты держат через конструкторNewAccount()и методы; - наследование: в Go его нет. Есть встраивание (embedding): методы встроенной структуры продвигаются наружу, но это композиция, а не отношение «является».
Dogсо встроеннымAnimalнельзя передать туда, где ждутAnimal; - полиморфизм: через интерфейсы, которые реализуются неявно, без слова
implements. Подходит любой тип с нужным набором методов, вызов идёт через динамическую диспетчеризацию. С Go 1.18 добавился параметрический полиморфизм на дженериках.
Хорошо прозвучит принцип «принимайте интерфейсы, возвращайте структуры» и то, что интерфейс в Go объявляют на стороне потребителя, а не рядом с реализацией.
Где спотыкаются
Называют встраивание наследованием и говорят, что Dog «переопределяет» метод Speak. Это затенение, а не переопределение: если метод Animal.Describe() внутри вызывает Speak(), сработает версия Animal, виртуальных методов у встроенной структуры нет.
Считают, что строчная буква делает поле приватным для типа, как private в Java. Граница видимости в Go это пакет.
Проектируют большие интерфейсы заранее, по образцу Java, на десяток методов. В Go это считается запахом: такой интерфейс трудно подменить в тестах и почти невозможно реализовать вторым типом.