Наследование структур в шаблоне фабрики - PullRequest
0 голосов
/ 02 августа 2020

Мне нужно создать наследника для некоторой структуры:

// Not interface, pure struct
type Base struct {
  A int
  B string
}

type Child struct {
  Base
  C bool
}

func (c *Child) SomeLoop() {
  for {
    // business logic
  }
}

создать дочерний экземпляр и вернуть его с фабрики

func maker() *Base {
  child := &Child {
    Base {
      A: 1
      B: "2"
    },
    C: false,
  }
  go child.Some()
  return child
}

Объекты, которые создаются с фабрики, используя как базовую структуру с полями A и B

o := maker()
fmt.Println(o.A, o.B) 

Но я не могу вернуть child как base из maker fun c. Как реализовать этот узор?

1 Ответ

0 голосов
/ 02 августа 2020

Golang не имеет наследования, только встраивание. Вы не можете вернуть child как *Base из maker(). Однако вы можете вернуть &child.Base (теряя ссылку на child в возвращаемом значении в процессе).

Самое близкое, что вы можете получить, - это определить interface{} для Base с «способностью» (функциями) возвращать значения A и B:

type BaseInterface interface { // Don't actually name it like this
    // You would usually omit the "Get", but then
    // we'd get a name conflict with the fields later.
    // This may be avoided by making them lowercase, i.e. private.
    GetA() int
    GetB() string
}

Затем вы можете реализовать это для *Child:

// Note how this implements BaseInterface for Child and *Child alike.

func (child *Child) GetA() int {
    return child.A
}

func (child *Child) GetB() string {
    return child.B
}

Затем вы можете вернуть его как BaseInterface и, при необходимости, позже выполнить утверждение типа, чтобы получить исходный тип *Child:

returnedValue.(*Child) // Yes, this really is what the syntax looks like.

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

...