Ответ
Go не является классическим объектно-ориентированным языком, как Java или C++, и в нем нет ключевого слова class
. Однако Go по-своему реализует основные принципы ООП, предлагая более прагматичный и композиционный подход.
Вот как Go подходит к трем столпам ООП:
1. Инкапсуляция
Инкапсуляция в Go достигается на уровне пакетов через управление видимостью идентификаторов (переменных, функций, типов, полей структур).
- Экспортируемое (Public): Если имя начинается с заглавной буквы (например,
MyVariable
), оно доступно из других пакетов. - Неэкспортируемое (Private): Если имя начинается со строчной буквы (например,
myVariable
), оно доступно только внутри того же пакета.
2. Композиция вместо Наследования
В Go нет наследования в классическом понимании. Вместо этого язык поощряет композицию через встраивание (embedding) структур.
При встраивании одной структуры в другую, поля и методы встроенной структуры «поднимаются» на уровень внешней. Это позволяет повторно использовать код, но это не является отношением «is-a» (является), как при наследовании, а скорее «has-a» (имеет).
3. Полиморфизм через Интерфейсы
Полиморфизм в Go реализуется с помощью интерфейсов. Интерфейс определяет набор методов. Любой тип, который реализует все методы интерфейса, неявно (утиная типизация) удовлетворяет этому интерфейсу.
Это позволяет писать функции, которые оперируют абстрактными типами (интерфейсами), не зная их конкретной реализации.
package main
import "fmt"
// 1. Полиморфизм: определяем интерфейс
type Speaker interface {
Speak() string
}
// 2. Инкапсуляция: поля с маленькой буквы (name) не видны вне пакета
type Dog struct {
name string
}
func (d Dog) Speak() string {
return "Woof!"
}
type Cat struct {
name string
}
func (c Cat) Speak() string {
return "Meow!"
}
// Эта функция работает с любым типом, удовлетворяющим интерфейсу Speaker
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{name: "Rex"}
cat := Cat{name: "Murzik"}
MakeSound(dog) // Выведет: Woof!
MakeSound(cat) // Выведет: Meow!
}