Задача: сделать разные структуры с общим методом и добавить в один массив для перебора в цикле. При этом метод должен изменять свойства владельца
Две структуры: Blinker и Jumper. Первый может мигать (имеет цвет), второй прыгать (имеет высоту), но оба могут передвигаться (Move)
Для передвижения определяю интерфейс Movable и структуру Entity, реализующую этот интерфейс. В Blinker и Jumper встраиваю Entity
type Movable interface {
Move()
}
type Entity struct {
x, y int
}
func (e Entity) Move() {
e.x += 1
e.y += 1
}
type Blinker struct {
Entity
color string
}
type Jumper struct {
Entity
alt int
}
Теперь я могу определить список, в который можно поместить и Blinker и Jumper по интерфейсу для использования метода Move
type Movers []Movable
var list Movers
Создаю по одному экземпляру мигателя и прыгуна, добавляю в список и передвигаю. Вывожу в консоль.
func main() {
blinker := Blinker{color: "blue"}
jumper := Jumper{alt: 8}
list = append(list, blinker)
list = append(list, jumper)
for _, item := range list {
item.Move()
}
for _, item := range list {
fmt.Println(item)
// {{0 0} blue}
// {{0 0} 8}
}
}
Ан нет, не передвинулись. Я могу в метод Move передать контекст по ссылке, но тогда он перестаёт реализовывать интерфейс
func (e *Entity) Move() {}
// Blinker does not implement Movable (Move method has pointer receiver)
Как исправить это, оставив разделение на разные структуры и возможность юзать общий метод в общем списке?
Код полностью
package main
import "fmt"
type Movers []Movable
type Movable interface {
Move()
}
type Entity struct {
x, y int
}
func (e Entity) Move() {
e.x += 1
e.y += 1
}
type Blinker struct {
Entity
color string
}
type Jumper struct {
Entity
alt int
}
var list Movers
func main() {
blinker := Blinker{color: "blue"}
jumper := Jumper{alt: 8}
list = append(list, blinker)
list = append(list, jumper)
for _, item := range list {
item.Move()
}
for _, item := range list {
fmt.Println(item)
// {{0 0} blue}
// {{0 0} 8}
}
}
PS: В GO третий день, поэтому прошу прощения за терминологию и глупости