面向对象定义

面向对象三要素:

  • 封装:将属性(数据)和方法(操作)封装,提供访问控制,隐藏实现细节,暴露该暴露的
  • 继承:子类可以从父类直接获得属性和方法,减少重复定义。子类中如果与父类不同,可以自己定 义新的属性和方法,也可以覆盖同名的属性和方法
  • 多态:前提是继承和覆盖,使得子类中虽然使用同一个方法,但是不同子类表现不同,就是不同的态

实现了以上特征的语言,才能成为面向对象编程范式语言。 严格意义来说,Go语言就是不想实现面向对象编程范式。但是面向对象又有一些不错的特性,Go语言 通过组合的方式实现了类似的功能。 只能说,Go语言实现了一种非常有自我特征的面向对象。

封装

通过结构体,可以把数据字段封装在内,还可以为结构体提供方法。

访问控制:

  • 属性、方法标识符首字母大写,实现了对包外可见的访问控制
  • 属性、方法标识符首字母小写,仅包内可见
  • 这些一定程度上实现了public、private的访问控制

构造函数

Go没有提供类似C++、Java一样的构造函数、析构函数。在Go中,用构造结构体实例的函数,这个函数 没有特别的要求,只要返回结构体实例或其指针即可(建议返回指针,不然返回值会拷贝)。习惯上, 构造函数命名是New或new开头。如果有多个构造函数,可以使用不同命名函数,因为Go也没有函数重载。通过不同的函数名来模拟构造函数重载。

type Animal struct {
 name string
 age  int
}
func NewDefaultAnimal() *Animal {
 return &Animal{"nobody", 1}
}
func NewAnimal(name string, age int) *Animal {
 return &Animal{name, age}
}

继承

Go语言没有提供继承的语法,实际上需要通过匿名结构体嵌入(组合)来实现类似效果。

package main
import "fmt"
type Animal struct {
 name string
 age  int
}
func (*Animal) run() {
 fmt.Println("Animal run~~~")
}
type Cat struct {
 Animal // 匿名结构体嵌入
 color  string
}
func main() {
 cat := new(Cat)
 cat.run()
    cat.Animal.run()
}

通过匿名结构体嵌入,子结构体就拥有了父结构体的属性name、age,和run方法。

覆盖

覆盖override,也称重写。不是重载overload。

// 为Cat增加一个run方法,这就是覆盖。
func (*Cat) run() {
 fmt.Println("Cat run+++")
}

上例增加run方法是完全覆盖,就是不依赖父结构体方法,重写功能。 如果是依赖父结构体方法,那就要在子结构体方法中显式调用它。

func (c *Cat) run() {
 c.run()        // 这里不可这样写,成递归了
 c.Animal.run() // 这是调用父结构体方法。
 fmt.Println("Cat run+++")
}

多态

Go语言不能像Java语言一样使用多态,但可以通过引入interface接口来解决。

package main
import "fmt"
type Runner interface {
 run()
}
type Animal struct {
 name string
 age  int
}
func (*Animal) run() {
 fmt.Println("Animal run~~~")
}
type Cat struct {
 Animal // 匿名结构体嵌入
 color  string
}
func (c *Cat) run() {
 c.Animal.run()
 fmt.Println("Cat run+++")
}
type Dog struct {
 Animal // 匿名结构体嵌入
 color  string
}
func (d *Dog) run() {
 d.Animal.run()
 fmt.Println("Dog run+++")
}
func test(a Runner) { // 多态
 a.run()
}
func main() {
 // var a Animal = Cat{} // Go做不到这样赋值
 // a.run() // Go无法写出这2行,用接口
    
 d := new(Dog)
 d.name = "snoopy"
 test(d)
 c := new(Cat)
 c.name = "Garfield"
 test(c)
 test(d)
}
示例

test使用同一个类型的同一个接口却表现不同,这就是多态。

posted on 2023-07-05 20:09  自然洒脱  阅读(71)  评论(0编辑  收藏  举报