• 5 面向对象


    1 类型系统

    1.1给类型添加方法

    // 为类型添加方法
    type Integer int  // 定义一个新类型Integer, 它与int类型相同
    
    func (a Integer) Less(b Integer) bool {    // 给Integer类型添加新方法 less, less 方法输入一个整数,返回布尔值
        return a < b  // 当前整数a调用less方法要传入一个整数b, 如果a<b,返回true
    }

    如果我们想在方法中修改对象,这种时候必须就要用到指针

    func (a *Integer) Add (b Integer) {
        *a += b
    }
    
    func main()  {
        a := Integer(10)
        a.Add(5)
        fmt.Println("a is : ", a)
    }

     1.2 值语义和引用语义

    b = a
    b.Modyfy()
    // 如果a的值收到影响则a为引用类型,否则为值类型

    值类型的数据:

    • 基本数据类型
    • 符合类型: 数组, 结构体, 指针
    // 数组想表达引用
    var a = [3]int{1,2,3}
    var b = &a
    b[1]++
    fmt.Println(a, *b)

    类似引用类型的数据:

    1. 数组切片 : 指向数组的一个区间
    2. map : 键值对
    3. channel : 执行体间的通信设施
    4. 接口 : 对一组满足某个契约的类型的抽象

    1.3 结构体

    定义矩阵类型

    type Rect struct {。      // 定义矩形类型
        x, y float64
        width, height float64
    }
    
    func (r *Rect) Area() float64{    //定义成员方法计算矩形面积
        return r.width * r.height
    }

    2. 初始化

    初始化Rect类型的实例

    rect1 := new(Rect)
    rect2 := &Rect{}
    rect3 := &Rect{0, 0, 100, 200}
    rect4 := {100, height:200}

    3 匿名组合

    type Base struct {   // 定义Base类
        Name string
    }
    
    func (base *Base) Par() {   // Base类实现Par方法和Run方法
        fmt.Println("par in Base")
    }
    
    func (base *Base) Run() {    
        fmt.Println("run in base")
    }
    
    type Foo struct {      // Foo类继承Base类
        Base
    }
    
    func (foo *Foo) Run() {    // Foo类重写Run方法,先执行Base的Run方法在执行自己的代码
        foo.Base.Run()
        fmt.Println("run in foo")
    }
    
    func main()  {
        foo := new(Foo)  // 实例化一个foo对象,该对象有继承自父类的Par方法和自己的Run方法
        foo.Par()
        foo.Run()
    }

     4.接口

    4.1 非侵入式接口

    go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口

    例如:

    type File  struct{
    
    }
    
    func (f *File) Read (buf []byte) (n int, err error){
        return
    }
    
    func (f *File) Write(buf []byte) (n int, err error) {
        return
    }
    
    func (f *File) Seek (buf []byte) (n int, err error) {
        return
    }
    
    func (f *File) Close () (e error) {
        return
    }
    
    type IFile interface {
        Read(buf []byte)(n int, err error)
    }
    
    type IReader interface {
        Read(buf []byte)(n int, err error)
        Write(buf []byte)(n int, err error)
        Close(buf []byte)(n int, err error)
    }
    
    func main()  {
        var file1 IFile = new(File)
        fmt.Println(file1)
    }

    我们定义了一个File类,并实现了Read, Write, Seek, Close等方法。我们有IFile,IReader接口,尽管File类没有从这些接口继承,甚至不知道这些接口的存在,但是File类实现了这些接口,可以进行赋值

    4.2 接口赋值

    接口赋值的两种情况:

      1. 将对象赋值给接口

      2. 将一个接口赋值给另一个接口

    type Integer1 int
    
    func (a Integer1)Less(b Integer1) bool {
        return a < b
    }
    
    func (a *Integer1)Add(b Integer1)  {
        *a += b
    }
    
    type Lessadd interface {
        Less(b Integer1) bool
        Add(b Integer1)
    }
    
    type Less interface {
        Less(b Integer1) bool
    }
    
    func main()  {
        int1 := Integer1(5)
      // 将对象赋值给接口
    var ld Lessadd = &int1 //注意这两种情形的区别,因为Integer1类Add方法中我们要改变自身需要传递指针,所以在给接口赋值时也要传递指针。否则编译不通过 var ll Less = int1 // 这里不需要传递指针 fmt.Println(int1, ld.Less(6), ll) }

     在go语言中,只要两个接口拥有相同的方法列表,次序不同不要紧,那么他们就是等同的,可以相互赋值

    package one
    
    type ReaderWriter interface {
        Read(buf []byte) (n int, err error)
        Write(buf []byte) (n int, err error)
    }
    package two
    
    type IStream interface{
        Write(buf []byte)(n int, err error)
        Read(buf []byte)(n int, err error)
    }

    两个包中分别有两个接口,这两个接口有同样的方法列表,只是次序不同,他们可以相互赋值

    func main()  {
        var f1 two.IStream = new(File)
        var f2 one.ReaderWriter = f1
        var f3 two.IStream = f2
        fmt.Println(f1, f2, f3)
    }

    接口赋值并不要求两个接口完全的等价,只要A的方法列表B包含在的方法列表中,那么B的对象即可赋值给A接口

    package main
    
    import "fmt"
    
    type Animal interface{
        Speaking() string
    }
    
    type Cat struct{}
    
    func (c *Cat) Speaking()string  {
        return "喵喵喵"
    }
    
    type Sheep struct {}
    
    func (s Sheep)Speaking()string  {
        return "咩咩咩"
    }
    
    type Zhangbin struct {}
    
    func (z Zhangbin)Speaking()string  {
        return "汪汪汪"
    }
    
    
    
    func main()  {
            var animals = []Animal{&Cat{}, Sheep{}, Zhangbin{}}    // 注意这里必须使用指针来实例化cat对象,因为cat的指针有speaking方法,而cat对象本身不具备speaking方法
            fmt.Println(animals)
        }

    4.3 接口查询

    type Writer interface {
        Write(buf []byte)(n int, err error)
    }
    
    func main()  {
        var f1 two.IStream = new(File)
        var f2 one.ReaderWriter = f1
        var f3 two.IStream = f2
    
        var f4 Writer = f1   // IStream实现了Write方法,所以可以赋值给Writer
        //var f5 two.IStream = f4  // 因为Writer没有实现Read方法,所以不能赋值给IStream
    
    
        fmt.Println(f1, f2, f3, f4, f5)
    }
    var file1 Writer = ...
    if file5, ok := file1.(two.IStream);ok {
        ...  
    }
    
    
    // if语句查询file1接口指向的对象实例是否实现了two.IStream接口
    type File struct {}    // 创建File类, 这个类实现了 Write, Read, Close方法
    
    func (f *File)Write()  {
        return
    }
    
    func (f *File)Read()  {
        return
    }
    
    func (f *File)Close()  {
        return
    }
    
    type WR interface{           // WR接口
        Write()
        Read()
    }
    
    type W interface {            // W接口
        Write()
    }
    
    func main()  {
            var wr1 W = new(File)
            _, ok := wr1.(WR)            // 查看wr1指向的对象是否实现了了WR接口
            fmt.Println(wr1, ok)
        }

    查询接口所指向的对象实例是否为某个类型

    var file1 Writer = ...
    if file6, ok := file1.(*File); ok {
        ...
    }

    4.4 类型查询

    type File struct {}
    
    func (f *File)Write()  {
        return
    }
    
    func (f *File)Read()  {
        return
    }
    
    func (f *File)Close()  {
        return
    }
    
    type WR interface{
        Write()
        Read()
    }
    
    type W interface {
        Write()
    }
    
    func main()  {
            var wr1 WR = new(File)
            _, ok := wr1.(WR)
            fmt.Println(wr1, ok)
            switch wr1.(type){          // 类型查询语句
            case W:
                fmt.Println("type is W")
            case WR:
                fmt.Println("is WR")
            }
        }

    4.5 接口组合 

    type ReadWriter interace {        // ReadWriter接口将Reader接口和Writer接口组合起来
        Reader
        Writer
    } 

    4.6 Any类型

    go语言中任何对象实例都满足空接口interface{}, 所以interface{} 看起来像是可以指向任何对象的Any类型

    var v1 interface{} = 1
    var v2 interface{} = "abc"
    var v3 interface{} = &v2
    var v4 interface{} = struct{ X int }{1}
    var v5 interface{} = &struct{ X int }{1}

    当函数可以接受任意的对象实例时, 我们会将其声明为interface{}

    func Printf(fmt string, args ...interface{})
    func Println(args ...interface{})

                                                                                                                                                                                                                                       

  • 相关阅读:
    jquery获取父元素或父节点的方法
    JS省份联级下拉框
    全国各省、市名称(包括县级市)
    让Vs2010支持 Css3+HTML5
    Sql Server 事务/回滚
    Windows.Forms Panel 动态加载用户控件 UserControl
    C/C++ 运算符 & | 运算
    WPF
    SQL Server 数据库定时自动备份【转】
    如何编写更棒的代码:11个核心要点
  • 原文地址:https://www.cnblogs.com/zhangjian0092/p/12358209.html
Copyright © 2020-2023  润新知