dtlc84438 2016-05-17 20:13
浏览 10

具有处理程序功能时如何嵌入类型?

I'm working with a library that implements a type which accepts handlers and calls them for you when it should. I'd like to create a supertype that embeds the type and has properties beyond what the embedded type does. And I'd like to be able to use these properties in a handler.

Using my type as an argument fails the type checking, using the base type in handler decl works, but then I cant access the new fields. I am new to go, & would love to know how to do this, or what to suggest in changing the library to enable (Interfaces instead of the handler decl?)...

Contrived example:

    package main

    type Animal struct {
        Color   string
        feeders map[string]feeder
    }
    type feeder func(*Animal, string) string

    func (a *Animal) addFeeder(name string, fn feeder) {
        a.feeders[name] = fn
    }

    type mamal struct {
        Animal
        hair string
    }

    func feedHuman(m *mamal, food string) string {
        return "you got " + m.Color + " " + m.hair + " hair in your " + food
    }

    func main() {
        a := mamal{Animal{Color: "red"}, "bushy"}
        a.addFeeder("man", feedHuman)
        // fails to compile feedHuman needs to take *Animal but then cant access hair"
    }
  • 写回答

1条回答 默认 最新

  • dongshi2836 2016-05-17 21:02
    关注

    You are right, you cannot do that because a mamal is not an Animal. There is no inheritance in go so this is not a solution. But you can achieve this behaviour with interfaces. By the way, your code does not work because you didn't initialize the feeders map, so you will get a problem after compilation.

    Solution 1: Use type assertion

    package main
    
    import "fmt"
    
    type Animal struct {
        Color   string
        feeders map[string]feeder
    }
    type feeder func(interface{}, string) string
    
    func (a *Animal) addFeeder(name string, fn feeder) {
        a.feeders[name] = fn
    }
    
    type mamal struct {
        Animal
        hair string
    }
    
    func feedHuman(i interface{}, food string) string {
        m := i.(mamal)
        return "you got " + m.Color + " " + m.hair + " hair in your " + food
    }
    
    func main() {
        a := mamal{Animal{feeders: make(map[string]feeder), Color: "red"}, "bushy"}
        a.addFeeder("man", feedHuman)
        fmt.Println(a.feeders["man"](a, "pineapple"))
        // => you got red bushy hair in your pineapple
    }
    

    This is a bit dangerous because if the interface you pass is not a mamal, it will panic.

    Second solution: Use a Feeder interface

    package main
    
    import "fmt"
    
    type Feeder interface {
        Feed(string) string
    }
    
    type Animal struct {
        Color   string
        feeders map[string]Feeder
    }
    
    func (a *Animal) addFeeder(name string, feeder Feeder) {
        a.feeders[name] = feeder
    }
    
    type mamal struct {
        Animal
        hair string
    }
    
    func (m *mamal) Feed(food string) string {
        return "you got " + m.Color + " " + m.hair + " hair in your " + food
    }
    
    func main() {
        a := &mamal{Animal{Color: "red", feeders: make(map[string]Feeder)}, "bushy"}
        a.addFeeder("man", a)
        fmt.Println(a.feeders["man"].Feed("pineapple"))
        // you got red bushy hair in your pineapple
    }
    

    Though it works just as fine, it limits the number of handlers to one, so I do not think this is what you seek.

    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?