起源
面向对象:封装、继承、多态。
与面向过程相比,面向对象增加了对象的概念,所谓对象就是将软件开发中的过程进行结构化抽象,与现实中的事务相对应,以便于更好描述有事务的发展过程,这是一个哲学问题。
用面向对象的思想开发的软件天生具有很强设计性,比如面向对象中的圣经:设计模式。
但是语言一直在进化,一味的追求面向对象,一味的最求设计,只会增加软件的复杂度。
流行的面向对象语言有很多,比如c++,c#,java等,这里拿c#来举个例子,c#中面向对象中结构化设计包涵:类,抽象类,接口;函数实现包涵:抽象函数,虚函数,函数重载;关系实现包涵:继承,约定等。光理解上面者一堆概念就够你摸索一阵子了,如果在现实的开发中更加过分,一个间间单单的小业务,通过面向对象就能搞出一个庞大的代码结构,如果最后设计出来了还好,设计不出来岂不是既费时又费心。有人可能说了:小业务,要啥设计,一堆操作猛如虎,别人一看是垃圾。
重点
如果你之前是面向对象的重度使用者,看到Go的面向对象肯定觉得垃圾,没有错确实挺垃圾的,但是垃圾的恰到好处,虽然不强大但是绝对好用,包括语法也好用,何其简单,何其粗暴,用了Go你会觉得,打工其实也是一件快乐的事情。
Go中的面向对象
接口
下面定义两个接口,一个Animal接口,一个Dog接口
type IAnimal interface {
Eat()
}
type IDog interface {
Say()
Sit()
}
类(接口体)
Go中不支持类,但是可以使用struct模拟出与类一样的效果
type Dog struct {
Name string
Age int
}
dog:=Dog{Name:"小花",Age:3}
fmt.Printf("我叫:%s,现在:%d个月大",dog.Name,dog.Age)
// out
我叫:小花,现在:3个月大
让小花自我介绍
下面我们给小花添加一个自我介绍的方法
func (dog Dog) Say() {
fmt.Printf("我叫:%s,现在:%d个月大,wang!wang!",dog.Name,dog.Age)
}
dog:=Dog{Name:"小花",Age:3}
dog.Say()
//out
我叫:小花,现在:3个月大,wang!wang!
接口的实现
与其它语言一样,要实现某个接口必须实现接口对应的所有函数,上面的例子中,小花声明了一个Say()函数,但是没有声明Sit()函数,所以Dog没有实现IDog接口。
实现IDog接口的正确做法,再添加Sit()函数声明:
type Dog struct {
Name string
Age int
}
func (dog Dog) Say() {
fmt.Printf("我叫:%s,现在:%d个月大",dog.Name,dog.Age)
}
func (dog Dog) Sit(){
fmt.Printf("我坐下了,wang!wang!")
}
var dog IDog=Dog{Name:"小花",Age:3}
dog.Say()
fmt.Println()
dog.Sit()
// out
我叫:小花,现在:3个月大
我坐下了,wang!wang!
以上就是Go面向对象的所有实现,是不是特别简单,这样的语言你爱了吗?
Go面向对象中的坑
在其它的面向对象中,对象默认都是引用类型的,而Go中却不一样,Go中的对象是模拟的,所以与C保持一致。如果说C++是对C的升级,那么Go充其量算是C的一个开发框架。
type Dog struct {
Name string
}
func (dog Dog) RName(name string){
dog.Name=name
}
func main() {
dog:=Dog{
Name: "小花",
}
dog.RName("二蛋")
log.Println(dog.Name)
}
// out
小花
结果是不是很意外,将例子稍作改动:
// 仅做如下改动
func (dog *Dog) RName(name string){
dog.Name=name
}
// out
二蛋
通过上面两个例子对比,你明白了吗?
总结
- Go中仅支持接口的声明
- 实现接口就要实现接口中定义的所有函数
- Go不支持继承
- 定义对象方法时首选func (dog *Dog) RName(name string){}这种形式,除非你非常明确它们的区别。