作为当下比较热门的编程语言,社区中也时不时有针对Go 面向对象编程的讨论。俺整理了一部分有价值的内容,供大家参考。
(配图来自:gophers)
Go 是面向对象语言么?
是和否。 尽管 Go 有类型和方法,并允许面向对象的编程风格,但没有类型层次结构。 Go 中“接口”的概念提供了一种不同的方法,我们认为它易于使用,并且在某些方面更通用。 还有一些方法可以将类型嵌入到其他类型中,以提供与子类化类似但不完全相同的东西。 此外,Go 中的方法比 C++ 或 Java 中的方法更通用:它们可以为任何类型的数据定义,甚至是内置类型,例如普通的“未装箱”整数。 它们不限于结构(类)。 此外,由于缺乏类型层次结构,Go 中的“对象”感觉比 C++ 或 Java 等语言轻得多。
为何没有类(class)?
面向对象讨论 v友讨论
大多数人所谓的 OOP,其实都是说的“继承封装多态”这一套,但是,最早的 OOP 叫对象范式,对象范式的两个基本观念:
- 程序是由对象组成的;
- 对象之间互相发送消息,协作完成任务;
请问,有“继承、封装、多态”的定义吗?没有!!!这两个观念与后来我们熟知的面向对象三要素“封装、继承、多态”根本不在一个层面上。倒是与再后来的“组件、接口”神合。
那 Go 中怎么满足上面两点的呢,我们可以使用 struct 来表示对象。
func main() {
dog := Dog{Breed: "husky", Color: "black and white"}
fmt.Println(dog.Breed)
fmt.Println(dog.Speak())
}
type Dog struct {
Breed string
Color string
}
func (d Dog) Speak() string {
return "Woof!"
}
上面声明了 Dog 结构体,包含品种和颜色两个属性,另外给 Dog 增加了说话的方法。
按照上面的理念,我们定义husky为字符串类型,同样增加了说话的方法,问:husky是对象么?
当然是,虽然它内部只能维护一个变量。
func main() {
h := husky("stupid dog")
fmt.Println(h)
fmt.Println(h.Speak())
}
type husky string
func (h husky) Speak() string {
return "Woof!"
}
“继承、封装、多态” 在Go中如何实现?
继承
Go 没有 extends 关键字显式声明继承关系,不过可以通过内嵌匿名成员方式达到继承目的。
我们来看以下代码:
type Superpower struct {
name string
}
func (s Superpower) Biu() string {
return "Biu biu biu!"
}
type Dog struct {
Breed string
Color string
Superpower
}
func (d Dog) Speak() string {
return "Woof!"
}
将 Superpower 嵌入 Dog 中即可使用 Superpower 的方法和属性。
dog := Dog{}
fmt.Println(dog.Biu())
封装
在 Go 语言中没有 public、private、protected 这样的访问控制修饰符,它是通过字母大小写来控制可见性的。
如果定义的常量、变量、类型、接口、结构、函数等的名称是大写字母开头,这表示它们能被其它包访问或调用(相当于 public);非大写开头就只能在包内使用(相当于 private)。
示例代码:
type Dog struct {
breed string
Color string
Superpower
}
func (d Dog) Speak() string {
return "Woof!"
}
func (d Dog) GetBreed() string {
return d.breed
}
func (d Dog) SetBreed(breed string) {
d.breed = breed
}
多态
在面向对象中,多态的特征为:不同对象中同种行为的不同实现方式。在 Go 语言中可以使用接口实现这一特征。
Go 中没有 implements 关键字;类型是否满足接口是自动确定的。如下代码,Dog 实现了 Speak 方法即实现了 Animal 接口。
type Animal interface {
Speak() string
}
type Superpower struct {
name string
}
func (s Superpower) Biu() string {
return "Biu biu biu!"
}
type Dog struct {
Breed string
Color string
Superpower
}
func (d Dog) Speak() string {
return "Woof!"
}
type Cat struct {
Breed string
Color string
Superpower
}
func (c Cat) Speak() string {
return "Meow!!"
}
func main() {
dog := Dog{Breed: "husky", Color: "black and white", Superpower: Superpower{
name: "biu",
}}
fmt.Println(dog.name)
fmt.Println(dog.Biu())
animals := []Animal{Dog{}, Cat{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}
总结
Go 可以以面向对象方式编程,使用 struct 封装状态,interface 封装行为。