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

来源:互联网 发布:sina邮箱端口imap 编辑:程序博客网 时间:2024/06/05 20:36

概述

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

封装,继承,多态

五大基本原则:

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

go继承

匿名字段/嵌入字段

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

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

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

实例(继承与多态)

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

package mainimport "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())}打印:spotmy name is spot and I am a pointer

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

package mainimport (    "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)//接口类型指向子类对象}打印:spotmy name is spot and I am a pointermy name is spot and I am a pointer
原创粉丝点击