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

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

Поэтому я написал этот пост, чтобы прояснить эту тему. Является ли Go объектно-ориентированным или нет?

Если вы привыкли думать на определенном языке, в зависимости от того, с какого языка вы пришли, у вас может быть другой подход к этой теме. Например, если вы пришли из C, очевидно, что в Go гораздо больше возможностей объектно-ориентированного программирования. Исходя из Java, код Go не выглядит объектно-ориентированным.

Что вам нужно сделать в этом случае, так это перестать думать на «другом языке» и сначала подумать с мышлением го.

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

ВПерейти FAQговорит:

Go - объектно-ориентированный язык?

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

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

Концепции сбора вишни

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

Нет классов, введите структуры

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

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

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

Без наследства

Нет понятия наследования. Из FAQ по Go:

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

Состав над наследованием

Этотхорошо известный принцип, также упоминаемый в книге «Банда четырех», часто встречается в коде Go.

При объявлении структуры мы можем добавить безымянное (анонимное) поле, в результате чего его поля и методы будут отображаться в структуре. Это называетсявстраивание структуры:

package main

import ( “fmt” )

type Dog struct { Animal } type Animal struct { Age int }

func (a Animal) Move() { fmt.Println(“Animal moved”) } func (a Animal) SayAge() { fmt.Printf(“Animal age: %d\n”, a.Age) } func main() { d := Dog{} d.Age = 3 d.Move() d.SayAge() }

играть в

Интерфейсы

Забудьте об интерфейсах в стиле Java и PHP. Интерфейсы Go очень разные, и одна из ключевых концепций заключается в том, что интерфейсы удовлетворяют требованиям.неявно.

Из FAQ по Go:

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

Интерфейсы обычно очень маленькие, вплоть до одного метода. В идиоматическом Go вы не увидите длинных списков методов.

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

Методы

У типов есть методы. Они определены вне определения типа с синтаксисом, который может напоминатьJavaScriptопределения метода прототипа:

function Person(first, last) {
    this.firstName = first;
    this.lastName = last;
}
Person.prototype.name = function() {
    return this.firstName + " " + this.lastName;
};
p = new Person("Flavio", "Copes")
p.name() // Flavio Copes

в Go тот же код записывается так:

package main

import ( “fmt” ) type Person struct { firstName string lastName string } func (p Person) name() string { return p.firstName + " " + p.lastName } func main() { p := Person{“Flavio”, “Copes”} fmt.Println(p.name()) }

Прикрепите методы к типам

Методы могут быть присоединены к любому типу, даже к базовым типам данных. Поскольку методы могут быть присоединены только к тому же пакету, в котором определен тип, мы не можем «обогатить» встроенные базовые типы, но мы можем обогатить любой именованный тип, который мы создаем, базовым представлением базового типа:

package main

import ( “fmt” )

type Amount int

func (a Amount) Add(add Amount) { a += add }

func main() { var a Amount a = 1 a.Add(2) fmt.Println(a) }

играть в

Функции

Подумайте о традиционном объектно-ориентированном языке программирования, таком как Java. Сколько раз вы определяли класс «Utils» с помощью статических методов?

Это сделано для того, чтобы обойти идею о том, что все является объектом, а определения функций должны находиться внутри классов. С Go такого не происходит, потому что в Go есть функции. В реальном мире не все должно быть объектом или методом. «Классы» и «объекты» очень полезны, но их нельзя использовать для всего.

В Go не все является объектом (и технически ничто не является объектом, но некоторые люди называют значения типа и переменные «объектами»), методы - это функции, связанные с типом, но Go также позволяет функциям жить вне объекта, как и C функции.

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

Меньше вздутия

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


Больше руководств по go: