为了账号安全,请及时绑定邮箱和手机立即绑定

未实现,方法类型错误

未实现,方法类型错误

Go
ibeautiful 2023-03-21 14:28:54
给定以下 Go 代码:package maintype CatToy interface {    Rattle() string}type Cat struct {}func (cat *Cat) Play(catToy CatToy) {    println("The cat is playing!", catToy.Rattle())}type DogToy interface {    Roll() string}type Dog struct {}func (dog *Dog) Play(dogToy DogToy) {    println("The dog is playing!", dogToy.Roll())}type SuperToy struct {}func (toy *SuperToy) Rattle() string {    return "Rattle!!!"}func (toy *SuperToy) Roll() string {    return "Rolling..."}type Pet interface {    Play(toy interface{})}func main() {    cat := &Cat{}    dog := &Dog{}    superToy := &SuperToy{}    // Working    cat.Play(superToy)    dog.Play(superToy)    // Not Working    pets := []Pet{cat, dog}    for _, pet := range pets {        pet.Play(superToy)    }}我收到这些错误:# command-line-arguments./main.go:65:16: cannot use cat (type *Cat) as type Pet in array or slice literal:    *Cat does not implement Pet (wrong type for Play method)        have Play(CatToy)        want Play(interface {})./main.go:65:21: cannot use dog (type *Dog) as type Pet in array or slice literal:    *Dog does not implement Pet (wrong type for Play method)        have Play(DogToy)        want Play(interface {})实现SuperToy了CatToy和DogToy。但是,当我创建一个接口Pet作为参数的接口时,我得到一个错误。我可以知道我怎样才能得到一个里面有猫和狗的数组/切片吗?我想遍历这个切片并为每个切片调用一个函数。我还想保留CatToy和DogToy接口。我也可以删除Pet界面。更多信息:未来我更有可能添加更多pets。我认为我不会添加更多操作,例如Play.
查看完整描述

3 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

我明白你想做什么,但这是不可能的:你的Cat和Dog类型没有实现Pet接口,因为它们的Play方法采用不同的类型,所以你不能只用Play你的SuperToy.


要解决此问题,您需要创建一个Toy接口,该接口同时具有Roll和Rattle方法以及 make Pet.Play,Cat.Play并将Dog.Play此接口作为参数。


package main


type Cat struct {

}


func (cat *Cat) Play(catToy Toy) {

    println("The cat is playing!", catToy.Rattle())

}


type Dog struct {

}


func (dog *Dog) Play(dogToy Toy) {

    println("The dog is playing!", dogToy.Roll())

}


type Toy interface {

    Roll() string

    Rattle() string

}


type SuperToy struct {

}


func (toy *SuperToy) Rattle() string {

    return "Rattle!!!"

}


func (toy *SuperToy) Roll() string {

    return "Rolling..."

}


type Pet interface {

    Play(toy Toy)

}


func main() {

    cat := &Cat{}

    dog := &Dog{}

    superToy := &SuperToy{}


    // Working

    cat.Play(superToy)

    dog.Play(superToy)


    // Not Working

    pets := []Pet{cat, dog}

    for _, pet := range pets {

        pet.Play(superToy)

    }

}

给出输出


The cat is playing! Rattle!!!

The dog is playing! Rolling...

The cat is playing! Rattle!!!

The dog is playing! Rolling...


查看完整回答
反对 回复 2023-03-21
?
皈依舞

TA贡献1851条经验 获得超3个赞

您可以让 Play 方法接受一个interface{},然后在方法内进行类型断言:


func (dog *Dog) Play(toy interface{}) {

    dogToy, isDogToy := toy.(DogToy)

    if !isDogToy {

        println("The dog does not know what to do with this toy!")

        return

    }

    println("The dog is playing!", dogToy.Roll())

}

Go Playground 上的完整可执行示例:


https://play.golang.org/p/LZZ-HqpzR-Z


查看完整回答
反对 回复 2023-03-21
?
12345678_0001

TA贡献1802条经验 获得超5个赞

这是另一个可行的解决方案:


package main


type CatToy interface {

    Rattle() string

}


type Cat struct {

    Toy CatToy

}


func (cat *Cat) Play() {

    println("The cat is playing!", cat.Toy.Rattle())

}


type DogToy interface {

    Roll() string

}


type Dog struct {

    Toy DogToy

}


func (dog *Dog) Play() {

    println("The dog is playing!", dog.Toy.Roll())

}


type SuperToy struct {

}


func (toy *SuperToy) Rattle() string {

    return "Rattle!!!"

}


func (toy *SuperToy) Roll() string {

    return "Rolling..."

}


type Pet interface {

    Play()

}


func main() {

    superToy := &SuperToy{}

    cat := &Cat{superToy}

    dog := &Dog{superToy}


    // Working

    cat.Play()

    dog.Play()


    // Working also

    pets := []Pet{cat, dog}

    for _, pet := range pets {

        pet.Play()

    }

}

该解决方案使Cat + CatToy和Dog + DogToy独立于main + SuperToy. 这允许提取以分离包。


查看完整回答
反对 回复 2023-03-21
  • 3 回答
  • 0 关注
  • 95 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号