axsmak
@axsmak
Создатель

Как реализовать метод интерфейса с передачей по ссылке?

Задача: сделать разные структуры с общим методом и добавить в один массив для перебора в цикле. При этом метод должен изменять свойства владельца

Две структуры: 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 третий день, поэтому прошу прощения за терминологию и глупости
  • Вопрос задан
  • 149 просмотров
Решения вопроса 1
yellow79
@yellow79
Senior Software Engineer
Как-то примерно вот так
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
01 мая 2024, в 02:11
5000 руб./за проект
01 мая 2024, в 00:29
2000 руб./за проект
01 мая 2024, в 00:20
15000 руб./за проект