Люди часто стопки вида документов с помощью рекурсивного метода. Например, предположите сортировку 100 документов с именами на них. Документы первого места в груды первой буквой, затем вид каждая груда.
Ищущие слова в словаре часто выполняются подобной двоичному поиску техникой, которая является рекурсивной.
В организациях, боссы часто дают команды начальникам отделов, которые в свою очередь дают команды менеджерам и так далее.
В комментарии вы задались вопросом, достаточно ли идеи встраивания для «полной замены наследования». Я бы сказал, что ответ на этот вопрос - «да». Несколько лет назад я очень кратко поигрался с OO-системой Tcl под названием Snit , которая использовала композицию и делегирование для исключения наследования. Snit по-прежнему сильно отличается от подхода Go, но в одном отношении у них есть общие философские основания. Это механизм для объединения частей функциональности и ответственности, а не иерархия классов.
Как утверждали другие, на самом деле речь идет о том, какие практики программирования хотят поддерживать разработчики языка. У каждого такого выбора есть свои плюсы и минусы; Я не думаю, что фраза «лучшие практики» здесь обязательно применима. Мы, вероятно, увидим, как кто-то в конце концов разработает уровень наследования для Go.
(Для любого читателя, знакомого с Tcl, я считаю, что Snit немного ближе к «ощущению» языка, чем [incr Tcl]
. Tcl - это все, что касается делегирования, по крайней мере по моему мнению.)
Решающий принцип Банды 4 - «предпочитать композицию наследованию»; Go заставляет следовать за ним; -).
Единственными реальными вариантами использования наследования являются:
Полиморфизм
Заимствование реализации из другого класса
Подход Go не совсем отображает 1-к-1, рассмотрим этот классический пример наследования и полиморфизма в Java ( на основе этого ):
//roughly in Java (omitting lots of irrelevant details)
//WARNING: don't use at all, not even as a test
abstract class BankAccount
{
int balance; //in cents
void Deposit(int money)
{
balance += money;
}
void withdraw(int money)
{
if(money > maxAllowedWithdrawl())
throw new NotEnoughMoneyException();
balance -= money;
}
abstract int maxAllowedWithdrawl();
}
class Account extends BankAccount
{
int maxAllowedWithdrawl()
{
return balance;
}
}
class OverdraftAccount extends BankAccount
{
int overdraft; //amount of negative money allowed
int maxAllowedWithdrawl()
{
return balance + overdraft;
}
}
Здесь наследование и полиморфизм вместе, и вы не можете перевести это на Go без изменения базовой структуры.
Я не углублялся в Go, но полагаю, это будет выглядеть примерно так:
//roughly Go? .... no?
//for illustrative purposes only; not likely to compile
//
//WARNING: This is totally wrong; it's programming Java in Go
type Account interface {
AddToBalance(int)
MaxWithdraw() int
}
func Deposit(account Account, amount int) {
account.AddToBalance(amount)
}
func Withdraw(account Account, amount int) error {
if account.MaxWithdraw() < amount {
return errors.New("Overdraft!")
}
account.AddToBalance(-amount)
return nil
}
type BankAccount {
balance int
}
func (account *BankAccount) AddToBalance(amount int) {
account.balance += amount;
}
type RegularAccount {
*BankAccount
}
func (account *RegularAccount) MaxWithdraw() int {
return account.balance //assuming it's allowed
}
type OverdraftAccount {
*BankAccount
overdraft int
}
func (account *OverdraftAccount) MaxWithdraw() int {
return account.balance + account.overdraft
}
Согласно примечанию, это полностью неправильный способ кодирования, поскольку Java выполняется на Go. Если бы кто-то написал такую вещь на Go, она, вероятно, была бы организована иначе, чем эта.
Я только сейчас изучаю Go, но, поскольку вы спрашиваете мнение, я предлагаю его на основе того, что мне известно до сих пор. Встраивание, по-видимому, типично для многих других вещей в Go, что является явной языковой поддержкой лучших практик, которые уже применяются в существующих языках. Например, как заметил Алекс Мартелли, «Банда четырех» говорит «предпочитать композицию наследованию». Go не только удаляет наследование, но и делает композицию более простой и мощной, чем в C ++ / Java / C #.
Я был озадачен комментариями типа «Go не предоставляет ничего нового, чего я уже не могу сделать на языке X» и "Зачем нам нужен другой язык?" Мне кажется, что с одной стороны Go не предоставляет ничего нового, чего раньше нельзя было сделать с помощью некоторой работы, но с другой стороны,