15.Golang的面向对象特性

1.封装

1.1.示例代码

obj1.go

package chapter12

import "fmt"

// 如果 类名 首字母大写,表示其他包也能够访问,否则只能当前包访问
type Hero struct {
    // 如果类的属性 首字母 大写,表示该属性是对外能够访问的,否则的化只能够类的内部访问
    Name  string
    Ad    int
    Level int
}

/*
func (hero Hero) Show() {
    fmt.Println("Name = ", hero.Name)
    fmt.Println("Ad = ", hero.Ad)
    fmt.Println("Level = ", hero.Level)
}

func (hero Hero) getName() string {
    return hero.Name
}

func (hero Hero) setName(newName string) {
    // this 是调用该方法的对象一个副本(拷贝)
    hero.Name = newName
}
*/
func (hero *Hero) Show() {
    fmt.Println("Name = ", hero.Name)
    fmt.Println("Ad = ", hero.Ad)
    fmt.Println("Level = ", hero.Level)
}

func (hero *Hero) getName() string {
    return hero.Name
}

func (hero *Hero) setName(newName string) {
    // this 是调用该方法的对象一个副本(拷贝)
    hero.Name = newName
}
func Run() {
    // 创建一个对象
    hero := Hero{
        Name:  "zhang3",
        Ad:    100,
        Level: 1,
    }

    hero.Show()

    //修改对象名字
    hero.setName("1i4")
    hero.Show()
}

obj_test.go

package chapter12

import "testing"

func TestRun(t *testing.T) {
    Run()
}

执行结果

=== RUN   TestRun
Name =  zhang3
Ad =  100
Level =  1
Name =  1i4
Ad =  100
Level =  1
--- PASS: TestRun (0.00s)
PASS
ok  

1.2 小结

2.继承

2.1.示例代码

obj2.go

package chapter12

import "fmt"

// Human 定义 结构体
type Human struct {
    name string
    sex  string
}

func (human *Human) Eat() {
    fmt.Println("Human.Eat()...")
}

func (human *Human) Walk() {
    fmt.Println("Human.Walk()...")
}

//=======================

// SuperMan 继承 Human
type SuperMan struct {
    Human //SuperMan类继承了Human类的方法
    level int
}

// 重定义父类的方式
func (superMan *SuperMan) Eat() {
    fmt.Println("SuperMan.Eat()....")
}

//子类的新方法
func (superMan *SuperMan) Fly() {
    fmt.Println("SuperMan.Fly()....")
}

func (superMan *SuperMan) print() {
    fmt.Println("name = ", superMan.name)
    fmt.Println("sex = ", superMan.sex)
    fmt.Println("levle = ", superMan.level)
}

// main
func Run2() {
    h := Human{
        name: "zhang3",
        sex:  "female",
    }
    h.Eat()
    h.Walk()

    // 初始化一个子类对象
    // 方式1
    // s := SuperMan{
    //  Human: Human{
    //      name: "li4",
    //      sex:  "man",
    //  },
    //  level: 10,
    // }
    // 方式2
    var s SuperMan
    s.name = "li4"
    s.sex = "man"
    s.level = 100

    s.Eat()  // 子类的eat
    s.Walk() // 父类的walk
    s.Fly()  // 子类的fly
    s.print()
}

执行结果

=== RUN   TestRun2
Human.Eat()...
Human.Walk()...
SuperMan.Eat()....
Human.Walk()...
SuperMan.Fly()....
name =  li4
sex =  man
levle =  100
--- PASS: TestRun2 (0.00s)
PASS
ok      

2.2.小结

3.多态

3.1.示例代码

obj3.go

package chapter12

import "fmt"

// 本质是一个指针
type AnimalIF interface {
    Sleep()
    GetColor() string // 获取动物的颜色
    GetType() string  // 获取动物的种类
}

// Cat 具体的类
type Cat struct {
    color string // 猫的颜色func (cat *Cat) Sleep() {
}

func (dog *Cat) Sleep() {
    fmt.Println("Cat is Sleep")
}

func (cat *Cat) GetColor() string {
    return cat.color
}

func (cat *Cat) GetType() string {
    return "Cat"
}

type Dog struct {
    color string
}

func (dog *Dog) Sleep() {
    fmt.Println("Dog is Sleep")
}

func (dog *Dog) GetColor() string {
    return dog.color
}

func (dog *Dog) GetType() string {
    return "Dog"
}

func showAnimal(animal AnimalIF) {
    animal.Sleep() // 多态
    fmt.Println("color = ", animal.GetColor())
    fmt.Println("kind = ", animal.GetType())
}

func Run3() {
    var animal AnimalIF // 接口的数据类型, 父类指针
    animal = &Cat{"Green"}

    animal.Sleep() // 调用的就是Cat的Sleep()方法

    animal = &Dog{"Yellow"}
    animal.Sleep() // 调用Dog的Sleep方法,多态现象

    fmt.Println("-----------")
    cat := Cat{"White"}
    dog := Dog{"Black"}
    showAnimal(&cat)
    showAnimal(&dog)
}

执行结果

=== RUN   TestRun3
Cat is Sleep
Dog is Sleep
-----------
Cat is Sleep
color =  White
kind =  Cat
Dog is Sleep
color =  Black
kind =  Dog
--- PASS: TestRun3 (0.00s)
PASS
ok  

3.2.interface{}是万能数据类型

obj4.go

package chapter12

import (
    "fmt"
)

// interface{}是万能数据类型
func myFunc(arg interface{}) {
    fmt.Println("myFunc is called...")
    fmt.Println(arg)

    // interface{} 该如何区分,此时引用的底层数据类型到底是什么?

    // 给 interface{} 提供 “类型断言” 的机制
    value, ok := arg.(string)
    if !ok {
        fmt.Println("arg is not string type")
    } else {
        fmt.Println("arg is string type, value = ", value)

        fmt.Printf("value type is %T\n", value)
    }
}

type Book struct {
    auth string
}

// main
func Run4() {
    book := Book{auth: "Golang"}
    myFunc(book)

    myFunc(100)
    myFunc("abc")
    myFunc(3.14)
}

执行结果

=== RUN   TestRun4
myFunc is called...
{Golang}
arg is not string type
myFunc is called...
100
arg is not string type
myFunc is called...
abc
arg is string type, value =  abc
value type is string
myFunc is called...
3.14
arg is not string type
--- PASS: TestRun4 (0.00s)
PASS
ok  

3.3.小结

4.总结

  • 封装
    • 结构体
    • 类名、属性名,方法名 首字母大小,可以被其他包访问;小写,只能在本包内访问
  • 继承
    • 子类继承父类的属性,同样拥有父类的方法
    • 子类可以重写父类的方法
    • 子类可以新增方法
    • 子类实例化方式有2种
      • 方式1: hero := Hero{
        Name: "zhang3",
        Ad: 100,
        Level: 1,
        }
      • 方式2:var s SuperMan
        s.name = "li4"
        s.sex = "man"
        s.level = 100
  • 多态
    • interface{} 是指针类型;通用的万能类型
    • interface{} 提供 类型断言 的机制 arg.(string)
    • 接口定义 type ${接口名} interface ,其中 typeinterface 是关键字
    • 接口定义的方法,实现需要全部实现 func (dog *Cat) Sleep() {
    • 父类类型的变量(指针)指向(引用)子类的具体数据变量,animal = &Cat{"Green"}
posted @ 2021-10-09 08:25  可可逗豆  阅读(59)  评论(0)    收藏  举报