面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程范型,同时也是一种程序开发的方法。它可能包含数据、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性[1],对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象[2][3]。Go语言也是一种面向对象编程的语言,但是和传统的编程语言有一些不同。但是Go也有很多传统OOP语言的特点:
- Methods on any defined type
- Polymorphism
- Namespacing
- Message Passing/Delegation
Go在定义2个对象的关系的方式上,说实话有点标新立异。
不同与传统的OOP语言的是,Go不支持Objects 和Classes,你可能会问,“如果Go不支持(Objects)对象那么如何进行面向对象编程呢?”。虽然Go没有明确的对象类型,但是Go有typs和methods来替代Objects 和Classes。Go提供的结构体
就是把使用各种数据类型定义
的不同变量组合起来
的高级数据类型。然后我们可以为这些数据类型声明方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。这看起来和传统的OOP语言的习惯差不多。然而Go却是不支持继承的。在Go中也没有继承类型。Go通过组合复用方式来实现继承。
组合复用
很多流行的编程语言都支持继承,继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。比如C++中的继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Vehicle { public: void drive() {} int getWheels() { return wheels } private: int wheels; }; class Car: public Vehicle { public: void drive() { /*Override with some behvaior */} void honk() { /* Some honking Logic */ } }; |
上面的代码中“Vehicle”类中定义了轮子和能够驾驶的方法,在子类中,“Car”类中,同样也有轮子但是重新定义了drive方法还增加了一个鸣喇叭(honk)方法。然而拥有这种模式设计的语言有些共同的缺点就是:使用起来不灵活。随着系统的复杂度增加,我们增加新的子类,孙子类,和曾孙类。我们的基类就会变得很难更改。因为在基类的中的改变就会影响到后代。可能会对整个系统造成不可预料的后果。
组合是一个很好的解决方案,对象的组合可以允许简单的对象组合成更大,更复杂的重用行为。在Go语言中你可以你可以嵌套各种类型来扩展他们的行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
type Person struct { Name string JobTitle string ShoeSize float32 } func (p Person) SayHello() { fmt.Println(“Hello, I’m “, p.Name) } func (p Person) GetJobTitle() { fmt.Println(“I’m a “, p.JobTitle) } type Doctor struct { Person Degree string } func (d Doctor) SayHello() { fmt.Println(“Hello, I’m Dr.”, d.Name, “, “, d.Degree) } func (d Doctor) Diagnose() { fmt.Println(“It’s Lupus.”) } |
在上面的代码中我们实现我们之前c++代码的示例的功能。首先我们创建了一个“Person”的基础类型,然后我们创建了一个“Doctor”的的类型,并且将“Person”嵌入其中。这样“Doctor”就会拥有了“Person”所有特性。这种方法比传统的继承更灵活。因为每个对象松散耦合,改变一个类型并不会引起其它行为的变化。本质上通过接口的组合复用能满足面向对象所有的需求,而且不需要复杂的继承限制。
什么是接口?
但是 Go 语言里有非常灵活的 接口 概念,通过它可以实现很多面向对象的特性。接口提供了一种方式来 说明 对象的行为:如果谁能搞定这件事,它就可以用在这儿。
接口定义了一组方法(方法集),但是这些方法不包含(实现)代码:它们没有被实现(它们是抽象的)。接口里也不能包含变量。
通过如下格式定义接口:
1 2 3 4 5 |
type Namer interface { Method1(param_list) return_type Method2(param_list) return_type ... } |
接口实现多态性
Go的通过接口能够方便的实现多态性,我们可以看一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package main import “fmt” type Animal interface { Type() string Swim() string IsFurry() bool } type Dog struct { Name string Breed string } type Frog struct { Name string Color string } func main() { f := new(Frog) d := new(Dog) zoo := […]Animal{f, d} for _, a := range zoo { fmt.Println(a.Type(), “ can “, a.Swim()) } } func (f *Frog) Type() string { return “Frog” } func (f *Frog) Swim() string { return “Kick” } func (d *Dog) Swim() string { return “Paddle” } func (d *Dog) Type() string { return “Doggie” } |
上面的代码看起来有一点做,那我们来看一个比较有实际意义的Go排序(Sort)功能的例子。这是一个基础包,然而开发者通过定义排序的类型实现在sort 包中“Interface”的接口,这个接口仅仅包含3个方法:“Len”, “Less”, and “Swap”.通过一个快速排序来调用这三个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
type Person struct { Name string Age int ShoeSize float32 } type PeopleByShoeSize []Person func (p PeopleByShoeSize) Len() int { return len(p) } func (p PeopleByShoeSize) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p PeopleByShoeSize) Less(i, j int) bool { return (p[i].ShoeSize < p[j].ShoeSize) } |
你可以看到一个“Person”的struct和一个叫“PeopleByShoeSize”的slice。我们实现了“Interface”的接口,我们看上面的“Less”方法,在方法中我们定义了我们排序的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
func main() { people := []Person{ { Name: “Person1”, Age: 25, ShoeSize: 8, }, { Name: “Person2”, Age: 21, ShoeSize: 4, }, { Name: “Person3”, Age: 15, ShoeSize: 9, }, { Name: “Person4”, Age: 45, ShoeSize: 15, }, { Name: “Person5”, Age: 25, ShoeSize: 8.5, }, } fmt.Println(people) sort.Sort(PeopleByShoeSize(people)) fmt.Println(people) } /* OUTPUT [{Person1 25 8} {Person2 21 4} {Person3 45 15} {Person4 25 8.5}] [{Person2 21 4} {Person1 25 8} {Person4 25 8.5} {Person3 45 15}] */ |
英文原文:https://medium.com/@gianbiondi/interfaces-in-go-59c3dc9c2d98#.5w1gw9yb0
有疑问加站长微信联系(非本文作者)