Advertisement
  1. Code
  2. Go

Let's Go: объектно-ориентированное программирование на Голанге

by
Read Time:7 minsLanguages:

Russian (Pусский) translation by Anna k.Ivanova (you can also view the original English article)

Go - это странная смесь старых и новых идей. У него очень освежающий подход, при котором он не боится отбросить устоявшиеся представления о том, «как делать вещи». Многие люди даже не уверены, является ли Go объектно-ориентированным языком. Позвольте мне сказать это прямо сейчас. Является!

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

Философия дизайна Go

Корни Go основаны на C и, в более широком смысле, на семействе Algol. Кен Томпсон в шутку сказал, что Роб Пайк, Роберт Грейнджер и он сам собрались вместе и решили, что они ненавидят C ++. Будь то шутка или нет, Go сильно отличается от C ++. Подробнее об этом позже. Go - это предельная простота Это подробно объясняется Робом Пайком в Меньше в геометрической прогрессии.

Go против Другие языки

В Go нет классов, объектов, исключений и шаблонов. Он имеет сборщик мусора и встроенный параллелизм. Самое поразительное упущение в отношении объектно-ориентированного подхода состоит в том, что в Go нет иерархии типов. Это отличается от большинства объектно-ориентированных языков, таких как C ++, Java, C #, Scala, и даже динамических языков, таких как Python и Ruby.

Go Особенности ОО

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

Структуры

Структура определяет состояние. Вот структура Существа. Она имеет поле «Имя» и логический флаг «Реал», который говорит нам, является ли это реальным существом или воображаемым. Структуры содержат только состояние и никакого поведения.

Методы

Методы - это функции, которые работают с определенными типами. У них есть пункт получателя, который указывает, на какой тип они работают. Вот метод Dump(), который работает со структурами Существ и печатает их состояние:

Это необычный синтаксис, но он очень явный и понятный (в отличие от неявного «this» или запутанного «self» Python).

Встраивание

Вы можете встраивать анонимные типы друг в друга. Если вы встраиваете безымянную структуру, то встроенная структура предоставляет свое состояние (и методы) непосредственно встраиваемой структуре. Например, в FlyingCreature встроена безымянная структура Creature, что означает, что FlyingCreature является Creature.

Теперь, если у вас есть экземпляр FlyingCreature, вы можете напрямую обращаться к его атрибутам Name и Real.

Интерфейсы

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

Объекты, которые реализуют все методы интерфейса, автоматически реализуют интерфейс. Не существует наследования или подклассов или ключевого слова "Implements". В следующем фрагменте кода тип Foo реализует интерфейс Fooer (по соглашению имена интерфейсов Go заканчиваются на «er»).

Объектно-ориентированный дизайн: путь Go

Давайте посмотрим, как Go соотносится со столпами объектно-ориентированного программирования: инкапсуляция, наследование и полиморфизм. Это особенности языков программирования на основе классов, которые являются наиболее популярными объектно-ориентированными языками программирования.

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

Инкапсуляция

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

Например, здесь, чтобы скрыть приведенный выше тип Foo и предоставить только интерфейс, который вы могли бы переименовать в строчный foo, и предоставить функцию NewFoo(), которая возвращает открытый интерфейс Fooer:

Тогда код из другого пакета может использовать NewFoo() и получить доступ к интерфейсу Fooer, реализованному внутренним типом foo:

Наследование

Наследование или подтипы всегда были спорным вопросом. Существует много проблем с наследованием реализации (в отличие от наследования интерфейса). Множественное наследование, реализованное в C ++, Python и других языках, страдает от проблемы смертельного алмаза смерти, но даже одиночное наследование не является пикником для хрупкой проблемы базового класса.

Современные языки и объектно-ориентированное мышление теперь предпочитают композицию, а не наследование. Go принимает это близко к сердцу и не имеет никакой иерархии типов. Это позволяет вам делиться деталями реализации через композицию. Но Go, в очень странном повороте (который, вероятно, возник из-за прагматических проблем), позволяет анонимную композицию посредством встраивания.

Для всех намерений и целей составление путем встраивания анонимного типа эквивалентно наследованию реализации. Встроенная структура так же хрупка, как и базовый класс. Вы также можете встроить интерфейс, который эквивалентен наследованию от интерфейса в таких языках, как Java или C ++. Это может даже привести к ошибке времени выполнения, которая не обнаруживается во время компиляции, если тип встраивания не реализует все методы интерфейса.

Здесь SuperFoo встраивает интерфейс Fooer, но не реализует его методы. Компилятор Go с радостью позволит вам создать новый SuperFoo и вызвать методы Fooer, но, очевидно, потерпит неудачу во время выполнения. Это компилируется:

Запуск этой программы приводит к панике:

Полиморфизм

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

Вот подробный пример, когда несколько существ (и дверь!), Которые реализуют интерфейс Dumper, создаются и сохраняются в срезе, а затем вызывается метод Dump() для каждого из них. Вы также заметите разные стили создания объектов.

Заключение

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

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

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.