LINUX.ORG.RU

История изменений

Исправление kaldeon, (текущая версия) :

как в Go реализуется вот такой элементарный паттерн

Напрямую — никак, ибо наследование реализации отсутствует. Это, кстати, защищает от проблемы хрупкого базового класса [1].

Но вообще аналогичный код пишется так:

1. Пишем derived1 и derived2

2. Пишем base, который при создании принимает derived1 или derived2 через общий интерфейс. Именно к нему будем обращаться в base.DoSomething.

3. В f передаём только инстанс base

В целом, прямое применение принципа “favor composition over inheritance.”

Важно и то, что интерфейс привязан только к base. Это расслабляет порядок написания: можно сначала реализовать derived1/derived2 и уже потом написать base/doer.

Код выглядит как-то так:

type doer interface{ Do() }

type base struct{ doer doer }

type derived1 struct{}

type derived2 struct{}

func (b *base) DoSomething() {
	b.doer.Do()
}

func (d *derived1) Do() { fmt.Println("hello world") }

func (d *derived2) Do() { fmt.Println("hello existence") }

func main() {
	b := &base{
		doer: &derived2{},
	}
	b.DoSomething()
}

[1]: https://en.wikipedia.org/wiki/Fragile_base_class

Исправление kaldeon, :

как в Go реализуется вот такой элементарный паттерн

Напрямую — никак, ибо наследование реализации отсутствует. Это, кстати, защищает от проблемы хрупкого базового класса [1].

Но вообще аналогичный код пишется так:

1. Пишем derived1 и derived2

2. Пишем base, который при создании принимает derived1 или derived2 через общий интерфейс. Именно к нему будем обращаться в base.DoSomething.

3. В f передаём только инстанс base

В целом, прямое применение принципа “favor composition over inheritance.”

Важно и то, что интерфейс привязан только к base. Это ослабляет порядок написания: можно сначала реализовать derived1/derived2 и уже потом написать base/doer.

Код выглядит как-то так:

type doer interface{ Do() }

type base struct{ doer doer }

type derived1 struct{}

type derived2 struct{}

func (b *base) DoSomething() {
	b.doer.Do()
}

func (d *derived1) Do() { fmt.Println("hello world") }

func (d *derived2) Do() { fmt.Println("hello existence") }

func main() {
	b := &base{
		doer: &derived2{},
	}
	b.DoSomething()
}

[1]: https://en.wikipedia.org/wiki/Fragile_base_class

Исходная версия kaldeon, :

как в Go реализуется вот такой элементарный паттерн

Напрямую — никак, ибо наследование реализации отсутствует. Это, кстати, защищает от проблемы хрупкого базового класса [1].

Но вообще аналогичный код пишется так:

1. Объявляем интерфейс doer

2. При создании base передаём в него конкретный инстанс, реализующий doer. Именно к нему base.DoSomething будет обращаться.

3. В f передаём только инстанс base.

В целом, прямое применение принципа “favor composition over inheritance.”

Код выглядит как-то так:

type doer interface{ Do() }

type base struct{ doer doer }

type derived1 struct{}

type derived2 struct{}

func (b *base) DoSomething() {
	b.doer.Do()
}

func (d *derived1) Do() { fmt.Println("hello world") }

func (d *derived2) Do() { fmt.Println("hello existence") }

func main() {
	b := &base{
		doer: &derived2{},
	}
	b.DoSomething()
}

Важно и то, что интерфейс привязан только к base. Это ослабляет порядок написания: можно сначала реализовать derived1/derived2 и уже потом ретроспективно написать base/doer.

[1]: https://en.wikipedia.org/wiki/Fragile_base_class