英文:
Pointer to interface in method args?
问题
你可以在第30行将Mouse
替换为Herbivore
接口。这样,你就可以传递实现了Herbivore
接口的不同结构体给eatingVictim
方法,而不仅仅是Mouse
。
英文:
How can I use interface Herbivore instead *Mouse in line 30?
I want to pass to method eatingVictim
different structs which implements Herbivore interface, not only Mouse
答案1
得分: 0
让我解释一下:
首先,在这个函数中:
func (predator Cat) eatingVictim(victim *Mouse) {
fmt.Println(predator.name + "的吃掉了" + victim.name)
predator.hungry = false
victim.alive = false
}
你想传递一个草食动物(Herbivore)。这是一个不好的解决方案,因为你在这里不会使用Herbivore接口的方法。更好的方法是定义另一个接口。
type Animal interface {
GetName() string
SetAlive(bool)
}
并为Mouse(和如果需要的话,Cat)实现它:
func (m *Mouse) GetName() string {
return m.name
}
func (m *Mouse) SetAlive(alive bool) {
m.alive = alive
}
然后将Predator接口更改为:
type Predator interface {
eatingVictim(victim Animal)
}
并为Cat实现它:
func (predator *Cat) eatingVictim(victim Animal) {
fmt.Println(predator.name + "的吃掉了" + victim.GetName())
predator.hungry = false
victim.SetAlive(false)
}
我需要提到的是,如果你希望修改原始的结构体,则需要传递一个指向结构体的指针,而不是一个结构体作为接收器参数:
在这里,Mouse结构体不会被修改,只会复制它。
func (herbivore Mouse) eatingGrass() {
fmt.Println(herbivore.name + "正在吃草.. ^___^")
herbivore.hungry = false
}
这是修复后的版本:
func (herbivore *Mouse) eatingGrass() {
fmt.Println(herbivore.name + "正在吃草.. ^___^")
herbivore.hungry = false
}
如果你想要更好的解释,请访问我的博客文章
最后一件事 - 作为最佳实践 - 如果你在类型的某个方法中使用了结构体指针,那么所有方法都应该使用指针。
最终解决方案:
package main
import "fmt"
type Predator interface {
eatingVictim(victim Animal)
}
type Herbivore interface {
eatingGrass()
}
type Animal interface {
GetName() string
SetAlive(bool)
}
type Cat struct {
name string
hungry bool
alive bool
}
type Mouse struct {
name string
hungry bool
alive bool
}
func (herbivore *Mouse) eatingGrass() {
fmt.Println(herbivore.name + "正在吃草.. ^___^")
herbivore.hungry = false
}
func (m *Mouse) GetName() string {
return m.name
}
func (m *Mouse) SetAlive(alive bool) {
m.alive = alive
}
func (predator *Cat) eatingVictim(victim Animal) {
fmt.Println(predator.name + "的吃掉了" + victim.GetName())
predator.hungry = false
victim.SetAlive(false)
}
func main() {
cat := Cat{"猫", true, true}
mouse := Mouse{"老鼠", true, true}
fmt.Println(cat)
fmt.Println(mouse)
mouse.eatingGrass()
cat.eatingVictim(&mouse)
fmt.Println(cat)
fmt.Println(mouse)
}
英文:
Let me explain:
First of all in this function:
func (predator Cat) eatingVictim(victim *Mouse) {
fmt.Println(predator.name + "'s eating victim " + victim.name)
predator.hungry = false
victim.alive = false
}
You want to pass Herbivore. This is a bad solution because you will not
use methods from Herbivore interface here. Better approach is to define
another interface.
type Animal interface {
GetName() string
SetAlive(bool)
}
And implement it for Mouse (and Cat if you wish):
func (m *Mouse) GetName() string {
return m.name
}
func (m *Mouse) SetAlive(alive bool) {
m.alive = alive
}
Then change interface Predator to:
type Predator interface {
eatingVictim(victim Animal)
}
and implement it for Cat
func (predator *Cat) eatingVictim(victim Animal) {
fmt.Println(predator.name + "'s eating victim " + victim.GetName())
predator.hungry = false
victim.SetAlive(false)
}
I need to mention that if you want your original structs to
be modified then you need to pass a pointer to struct, not a struct as
receiver argument:
Here Mouse struct will not be modified. Only a copy of it.
func (herbivore Mouse) eatingGrass() {
fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
herbivore.hungry = false
}
And here is the fixed version:
func (herbivore *Mouse) eatingGrass() {
fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
herbivore.hungry = false
}
If you want better explanation for this - then visit
my blog post
The last thing - as best practice - if you used Struct pointer in one of the methods of your
type then all of them should take a pointer to it.
Final solution:
package main
import "fmt"
type Predator interface {
eatingVictim(victim Animal)
}
type Herbivore interface {
eatingGrass()
}
type Animal interface {
GetName() string
SetAlive(bool)
}
type Cat struct {
name string
hungry bool
alive bool
}
type Mouse struct {
name string
hungry bool
alive bool
}
func (herbivore *Mouse) eatingGrass() {
fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
herbivore.hungry = false
}
func (m *Mouse) GetName() string {
return m.name
}
func (m *Mouse) SetAlive(alive bool) {
m.alive = alive
}
func (predator *Cat) eatingVictim(victim Animal) {
fmt.Println(predator.name + "'s eating victim " + victim.GetName())
predator.hungry = false
victim.SetAlive(false)
}
func main() {
cat := Cat{"cat", true, true}
mouse := Mouse{"mouse", true, true}
fmt.Println(cat)
fmt.Println(mouse)
mouse.eatingGrass()
cat.eatingVictim(&mouse)
fmt.Println(cat)
fmt.Println(mouse)
}
答案2
得分: 0
首先,你需要在接口中添加一个 Name()
方法和一个 SetAlive()
方法,并将 eatingGrass
导出:
type Herbivore interface {
Name() string
SetAlive(bool)
EatingGrass()
}
然后,你需要为 Mouse
实现 Name()
方法:
func (herbivore *Mouse) Name() string {
return Mouse.name
}
然后,对于 SetAlive
方法也做同样的操作。
现在你可以使用该接口:
func (predator Cat) eatingVictim(h Herbivore) {
fmt.Println(predator.name + "正在吃受害者" + h.Name())
predator.hungry = false
h.SetAlive(false)
}
注意:你应该为 *Mouse
实现所有的函数。因为当你设置结构体的某些值时,应该为指针实现方法,而不是结构体本身。否则可能会出现错误。
在实现时,最好像这样定义变量:
func (m *Mouse) Name() string {
return m.name
}
英文:
First you need to add a Name()
and a SetAlive()
method to the interface and make eatingGrass
exported:
type Herbivore interface {
Name()string
SetAlive(bool)
EatingGrass()
}
Then you need to implement Name()
for mouse:
func (herbivore *Mouse) Name()string {
return Mouse.name
}
Then do the same for SetAlive.
Now you can use the interface:
func (predator Cat) eatingVictim(h Herbivore) {
fmt.Println(predator.name + "'s eating victim " + h.Name())
predator.hungry = false
h.SetAlive(false)
}
Note: You should implement all the functions for the *Mouse
. Because when you set some values of the struct you should implement the method for the pointer and not the struct. Otherwise you can have bugs.
When implementing it is also better to define the varibale like this:
func (m *Mouse) Name() string {
return m.name
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论