A
A
Alexey Babiev2022-02-11 07:36:23
go
Alexey Babiev, 2022-02-11 07:36:23

How to implement an interface method with passing by reference?

Task: make different structures with a common method and add them to one array for iteration in a loop. In this case, the method must change the properties of the owner

. Two structures: Blinker and Jumper. The first can blink (has a color), the second can jump (has a height), but both can move (Move)
To move, I define the Movable interface and the Entity structure that implements this interface. In Blinker and Jumper I embed 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
}


Now I can define a list where both Blinker and Jumper can be placed by the interface to use the Move method
type Movers []Movable

var list Movers


I create one instance of the blinker and the jumper, add to the list and move. I output to the console.
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}
  }
}

No, they didn't move. I can pass the context to the Move method by reference, but then it stops implementing the interface
func (e *Entity) Move() {}
// Blinker does not implement Movable (Move method has pointer receiver)


How to fix this, leaving the division into different structures and the ability to use a common method in a common list?

Full code

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: It's the third day in GO, so I apologize for the terminology and stupidity

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Andrey Tsvetkov, 2022-02-11
@axsmak

Something like this

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question