Один из первых вопросов, который приходит на ум программистам, рассматривающим возможность перехода с объектно-ориентированных языков программирования, таких как Java и C#, на Golang, заключается в том, могут ли они применить те же принципы объектно-ориентированного программирования к Go. Ответ на этот вопрос можно найти в часто задаваемых вопросах go.dev;

Является ли Go объектно-ориентированным языком?

Да и нет. Хотя в Go есть типы и методы и допускается объектно-ориентированный стиль программирования, в нем нет иерархии типов. Концепция «интерфейса» в Go предлагает другой подход, который, по нашему мнению, прост в использовании и в некотором смысле более общий. Существуют также способы встраивания типов в другие типы, чтобы обеспечить нечто аналогичное — но не идентичное — подклассам. Более того, методы в Go более общие, чем в C++ или Java: их можно определить для любого типа данных, даже для встроенных типов, таких как простые, «неупакованные» целые числа. Они не ограничены структурами (классами).

Кроме того, отсутствие иерархии типов делает «объекты» в Go гораздо более легкими, чем в таких языках, как C++ или Java.

В этой статье мы обсудим, как концепции объектно-ориентированного программирования могут быть реализованы с помощью Go.

ИНКАПСУЛЯЦИЯ

Инкапсуляция защищает данные от внешних воздействий. В языках oop это делается на уровне объекта с помощью модификаторов доступа. Но в Голанге это делается на уровне пакета.

Go не имеет модификаторов доступа, таких как public, private или protected. Вместо этого есть экспортированные и неэкспортированные поля. Это различие связано с первыми буквами переменных. Нижний регистр означает неэкспортированный, заглавная буква означает экспортированный. Вы можете думать об этой разнице как о частной или общедоступной.

Еще одно отличие, которое мы видим, заключается в том, что здесь нет классов, но вместо этого у нас есть структуры. Причина в том, что Go появился как альтернатива C и C++, а структуры в основном используются в этих языках.

Это видимость на уровне пакета, поэтому переменные, начинающиеся со строчных букв, не видны снаружи пакета, в котором они находятся.

НАСЛЕДСТВО

В ООП компьютерные программы разработаны таким образом, что все является объектом, взаимодействующим друг с другом. Наследование — неотъемлемая часть языков ООП, позволяющая наследовать свойства одного класса другому. В основном это помогает повторно использовать код и устанавливать отношения между разными классами.

В Go мы можем использовать композиции для получения аналогичных результатов.

В приведенном выше примере структура car анонимно встраивается в другую структуру.

Это означает, что у нас есть прямой доступ к полям. Этот метод похож на то, к чему мы привыкли на стороне ООП.

В примере с мотоциклом мы назначаем одну структуру другому полю. Здесь к нему обращаются через его атрибуты.

Это различие определяет, как мы получаем доступ к данным, но оба работают как допустимый метод наследования.

КОНСТРУКТОРЫ

Конструкторы — это специальные функции для надежного создания нескольких экземпляров похожих объектов в языке ООП на основе классов.

В GO нет конкретного определения инициализации, но мы можем сделать то же самое, написав функцию.

Вышеприведенная функция NewCustomer выполняет ту же работу, что и конструкторы в языках oop.

Небольшое примечание: в Go существует концепция значений по умолчанию или пустых значений. Все чем-то инициализируется.

type Customer struct {
   Name string // " "
   Age  int    // 0
}

Эта ошибка, которая называется «NullReferenceException» в C#, «NullPointerException» в Java и при которой при инициализации не присваивается значение, не появляется в GO.

ПОЛИМОРФИЗМ

Golang поддерживает полиморфизм только через интерфейсы. Тип реализует интерфейс, если он предоставляет определения для всех методов, объявленных в интерфейсе.

В приведенном выше примере Guitar реализует интерфейс Instrument, предоставляя определение метода Play, который является единственным методом, объявленным в интерфейсе.

ПЕРЕЧИСЛЕНИЯ

Enum — это мощный тип данных для перечисляемых данных в языках oop. На стороне Go мы можем использовать только константы и назначать возрастающие значения с помощью iota. Хотя преимущество использования Enum в том, что нам не нужно задавать порядок явно.

ОБЩИЕ ОБРАЗЦЫ

Generics в Go — это новая концепция, появившаяся в версии 1.18. Это называется параметрами типа, и мы можем получить типы параметров функций из интерфейса, который мы должны определить, который может содержать несколько допустимых типов. Таким образом, мы можем избавиться от зависимости типа параметра и создать повторно используемые функции. Мы также можем использовать это для создания более сложных параметров типа.

В приведенном выше примере функция PlayInstrument принимает любое значение, которое соответствует контракту интерфейса «Инструмент».

Заключение

Golang продвигает интересный взгляд на объектно-ориентированное программирование с использованием интерфейсов, хотя он не предназначен для того, чтобы быть языком ООП. Реализация объектно-ориентированного программирования в Go невероятно гибкая, прямая и легкая.

Использование ООП в Go может показаться странным, но получение всех преимуществ Go без требовательных к ресурсам фреймворков, безусловно, является большим плюсом для многих разработчиков.