Go语言接口编程

558 阅读2分钟

面向对象编程的黄金法则

Program to an interface not an implementation

Favor object composition over class inheritance

C# 接口编程

定义接口

public interface IPerson
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    void Introduction();
    string GetName();
}

实现接口

public class Student : IPerson
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Student(string name)
    {
        Name = name;
    }
    
    public void Introduction()
    {
        Console.WriteLine("I am teacher:" + Name);
    }

    public string GetName()
    {
        return Name;
    }
}

Go 接口编程

接口定义

type Person interface {
   Introduction()
   GetName() string
}

student 实现接口

type Student struct {
   Name string
}

func (receiver Student) Introduction() {
   fmt.Println("I am student:" + receiver.Name)
}

func (receiver Student) GetName() string {
   return receiver.Name
}

func DemoRun() {
   student := Student{Name: "Moon"}
   student.Introduction()
}

比较Go 和 C#

C#的接口实现

  1. 定义接口。
  2. 定义对象Student,并继承于IPerson。
  3. 实现属性、接口。
  4. 支持类继承。子类拥有父类所有能力。

Go 的接口实现

  1. 定义接口Person。
  2. 定义对象Student。
  3. 实现接口。

总结比较

  • 可以看到Go的语法设计从定义,到实现有种大道至简的感觉。只要我Student实现了Person中的接口,那我就是实现了面向接口编程。
  • 而在C#、Java中,我们必须在类上声明继承的接口,再去实现具体的接口。其次C#、Java支持继承对象,可以实现父类方法的复用,把实现继承当作一种代码复用的方式,并不是一种值得鼓励的做法。所以往往我们会说组合优于继承
    • Java、C#都是单继承的语言,每个类只能有一个父类,一旦继承的位置被实现继承占据了,在想做接口继承就很难。
    • 当一个类继承了过的的接口,当借口足够复杂时,这会形成一个上帝类。
  • Java、C#这种面向对象语言,为了实现多态,引入了继承的概念,虽然在编码上带来了便捷性,但是带了不必要的心智负担:本来符合对象的唯一构造方法是组合,现在多了一个选择,继承。而Go语言,摒弃了继承的概念,全面强化组合能力。

Go 组合 多态

type Person interface {
   Introduction()
   GetName() string
}

type Info struct {
   Name string
   Age  int
}

type Student struct {
   Info
}

type Teacher struct {
   Info
}

func (receiver Teacher) Introduction() {
   fmt.Println("I am teacher:" + receiver.Name)

}

func (receiver Student) Introduction() {
   fmt.Println("I am student:" + receiver.Name)
}

func (info Info) GetName() string {
   return info.Name
}

// Say 多态
func Say(person Person) {
   person.Introduction()
   person.GetName()
}

func DemoRun() {
   student := Student{Info{Name: "Moon"}}
   student.Introduction()
   teacher := Teacher{Info{Name: "Moon"}}
   Say(student)
   Say(teacher)
}
  • Student 和 Teacher 都有Name、Age,这里我们可以抽出一个结构:Info,嵌入Student和Teacher。
  • Say函数,Person接口作为入参,实现了多态。

Go语言遵循了面对象编程方法的黄金法则——“Program to an interface not an implementation”。