面向对象思考及go实现继承与多态

概述

面向对象的三大基本特征:

封装,继承,多态

五大基本原则:

单一职责原则:指一个类设计的功能要单一,一个类只负责某一件事情。
开放封闭原则:一个模块在扩展方面是开放的,更改方面是封闭。如:网络模块,开始只有服务端功能,现 在加入客户端功能,应该在不修改服务端功能代码前提下,增加客户端功能的实现。
里氏替换原则:子类可以替换父类并出现在父类能够出现的任何地方。
1.子类可以扩展父类的功能,但不能改变父类原有的功能,尽量不要重写或重载。(这样写代码出错的几率会大大增加)
依赖倒置原则:具体依赖抽象,高层不能依赖底层, 应该依赖抽象。面向接口编程。
1.底层模块尽量都要有抽象类或接口
2.变量声明尽量是抽象类或接口
3.遵循里氏替换原则
接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上

go继承

匿名字段/嵌入字段

只提供类型,不写字段名,就是匿名字段,当匿名字段是一个struct时,这个struct所拥有的全部字段和方法都被隐试引入了当前定义的这个struct

利用匿名字段实现go的继承

1.匿名嵌入接口类型
2.匿名嵌入结构体
3.匿名嵌入结构体指针
字段名称就是嵌入类型名称

实例(继承与多态)

go在继承和聚合之间界限很模糊,看上去没区别,不同在于,继承自其它结构体的struct类型可以直接访问父类结构体的字段和方法。

package main

import "fmt"

type Pet struct {
    name string
}

type Dog struct {
    Pet   //匿名字段
    Breed string
}

func (p *Pet) Speak() string {
    return fmt.Sprintf("my name is %v", p.name)
}

func (p *Pet) Name() string {
    return p.name
}

func (d *Dog) Speak() string {
    return fmt.Sprintf("%v and I am a %v", d.Pet.Speak(), d.Breed)
}

func main() {
    d := Dog{Pet: Pet{name: "spot"}, Breed: "pointer"}//初始化匿名字段直接用字段名字即可
    fmt.Println(d.Name())
    fmt.Println(d.Speak())
}
打印:
spot
my name is spot and I am a pointer

通过接口指向子类对象,调用同一方法,作用于不同对象, 实现多态

package main

import (
    "fmt"
)

type Pet interface {
    Name() string
    Speak() string
    Play()
}

type pet struct {
    speaker func() string
    name    string
}

type Dog interface {
    Pet
    Breed() string
}

type dog struct {
    pet
    breed string
}

func NewPet(name string) *pet {
    p := &pet{
        name: name,
    }
    p.speaker = p.speak
    return p
}

func (p *pet) Play() {
    fmt.Println(p.Speak())
}

func (p *pet) Speak() string {
    return p.speaker()
}

func (p *pet) speak() string {
    return fmt.Sprintf("my name is %v", p.name)
}

func (p *pet) Name() string {
    return p.name
}

func NewDog(name, breed string) *dog {
    d := &dog{
        pet:   pet{name: name},
        breed: breed,
    }
    d.speaker = d.speak
    return d
}

func (d *dog) speak() string {
    return fmt.Sprintf("%v and I am a %v", d.pet.speak(), d.breed)
}

func Play(p Pet) {
    p.Play()
}

func main() {
    d := NewDog("spot", "pointer")
    fmt.Println(d.Name())
    fmt.Println(d.Speak())
    Play(d)//接口类型指向子类对象
}
打印:
spot
my name is spot and I am a pointer
my name is spot and I am a pointer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值