• 【玩转Golang】 通过组合嵌入实现代码复用


          应用开发中的一个常见情景,为了避免简单重复,需要在基类中实现共用代码,着同样有助于后期维护。

    如果在以往的支持类继承的语言中,比如c++,Java,c#等,这很简单!可是go不支持继承,只能mixin嵌入,且看下面的代码:

    type ManKind interface{
        Say(s string);   
        GetMouth()string
    }
    type Man struct{
       
    }
    func NewMan() ManKind{
        return &Man{};
    }
    func (this *Man)GetMouth()string{
        return "M0"
    }
    func (this *Man) Say(s string){
        fmt.Printf("
     Speak with mouth[%s] : "%s"",this.GetMouth(),s);
    }
    type StrongMan struct{
        Man
    }
    func NewStrongMan()ManKind{
        return &StrongMan{}
    }
    func (this*StrongMan)GetMouth()string{
        return "M1"
    }
    func main(){    
        NewMan().Say("good luck!")
        NewStrongMan().Say("good luck!")
    }

    如果支持继承,很明显应该输出

     Speak with mouth[M0] : "good luck!"
     Speak with mouth[M1] : "good luck!"

    但是在golang中只能输出:

     Speak with mouth[M0] : "good luck!"
     Speak with mouth[M0] : "good luck!"

    StrongMan中调用Say(),此时可以将指针传递到内嵌类,只是简单的指向了Man的方法,在ManKind中调用GetMouth就是ManKind自己的GetMouth,和StrongMan没有关系。

    当然,我们可以在StrongMan中覆盖Say方法

    func (this *StrongMan)Say(s string){
        fmt.Printf("
     Speak with mouth[%s] : "%s"",this.GetMouth(),s);
    }

    此时,当然可以正确输出,因为本来调用的就都是StrongMan自己的方法了,这又和我们的初衷相违背了。那么这种情况怎么实现呢?我的方法是,让Man再脏一点儿,把需要的东西传递给组合进来的类。

    给Man增加一个属性mouth,增加一个SetMouth方法,修改一下GetMouth方法,StrongMan的GetMouth方法删除掉,再修改一下NewStrongMan方法,最后的代码如下:

    package main
    
    import(
        "fmt"
    )
    
    type ManKind interface{
        Say(s string);    
        SetMouth(m string)
        GetMouth()string
    }
    type Man struct{
        ManKind    
        mouth string
    }
    func NewMan() ManKind{
        return &Man{mouth:"M0"};
    }
    func (this *Man)GetMouth()string{
        return this.mouth;
    }
    func (this *Man)SetMouth(s string){
        this.mouth=s;
    }
    func (this *Man) Say(s string){
        fmt.Printf("
     Speak with mouth[%s] : "%s"",this.GetMouth(),s);
    }
    type StrongMan struct{
        Man
    }
    func NewStrongMan()ManKind{
        sm := &StrongMan{}
      sm.SetMouth("M1");
      return sm; } func main(){ NewMan().Say(
    "good luck!") &NewStrongMan().Say("good luck!") }

     当然,如果你不愿意用Get、Set方法,也可以直接输出Man的Mouth属性。

    我总结的嵌入式编程要点:

    1,被嵌入的类的方法,只能访问他自己的字段,包装类即时声明了同名字段也没用。

    2,包装类可以覆盖嵌入类的方法,但是嵌入类访问不到,亦然访问自己的方法。只能在包装类中连同调用方法一同实现。

    3,包装类覆盖嵌入类字段后,亦然可以通过嵌入类的类名访问嵌入类的字段。

  • 相关阅读:
    R并行计算
    VMware虚拟机安装linux系统
    爬虫资料
    R-shiny服务器安装及配置
    数模国赛——致病基因
    vs 2013远程调试
    获取url的hash值
    JavaScript调试技巧之console.log()详解
    无法打开登录所请求的数据库
    location.host 与 location.hostname 的区别
  • 原文地址:https://www.cnblogs.com/dajianshi/p/4191531.html
Copyright © 2020-2023  润新知