美文网首页
Go 面向对象编程

Go 面向对象编程

作者: 如逆水行舟不进则退 | 来源:发表于2020-08-21 18:09 被阅读0次
    • struct 实例化方式
    package main
    
    import "fmt"
    
    type Teacher struct {
      name string
      age int8
      sex byte
    }
    
    func main() {
      // 1.var 声明方式实例化结构体。初始化方式为:对象.属性=值
      var t1 Teacher
      fmt.Println(t1)
      fmt.Printf("t1:%T, %v, %q \n", t1,t1,t1)
      t1.name = "Steven"
      t1.age = 35
      t1.sex = 1
      fmt.Println(t1)
      fmt.Println("------------")
      // 2.变量简短声明格式实例化结构体。初始化方式为:对象.属性 = 值
      t2:=Teacher{}
      t2.name = "David"
      t2.age = 30
      t2.sex = 1
      fmt.Println(t2)
      fmt.Println("------------")
      // 3.变量简短声明格式实例化结构体,声明时初始化,初始化方式为:属性:值,属性:值 可以同行,也可以换行(类似mag的用法)
      t3 := Teacher{
        name : "Json",
        age : 28,
        sex :1,
      }
      t3 = Teacher{name: "Json2", age: 27, sex:1}
      fmt.Println(t3)
      fmt.Println("------------")
      // 4.变量简短声明格式实例化结构体,声明时初始化,不写属性名,按属性顺序只写属性值
      t4 := Teacher{"Ruby",30,0}
      fmt.Println(t4)
      fmt.Println("------------")
    
    }
    
    
    
    
    • 结构体语法糖
    package main
    
    import "fmt"
    
    type Emp struct {
      name string
      age int8
      sex byte
    }
    
    func main() {
      // 使用new() 内置函数实例化 struct
      emp1 := new(Emp)
      fmt.Printf("emp1: %T, %v, %p \n", emp1,emp1,emp1)
    
      (*emp1).name = "David"
      (*emp1).age = 30
      (*emp1).sex = 1
      fmt.Println(emp1)
      // 语法糖写法
      emp1.name = "David2"
      emp1.age = 31
      emp1.sex = 1
      fmt.Println(emp1)
      fmt.Println("----------")
      SyntacticSugar()
    }
    
    func SyntacticSugar() {
      // 数组中的语法糖
      arr := [4]int{10,20,30,40}
      arr2 := &arr
      fmt.Println((*arr2)[len(arr)-1])
      fmt.Println(arr2[0]) // 语法糖
      // 切片中的语法糖  无语法糖
      slice := []int{100,200,300,400}
      slice1 := &slice
      fmt.Println((*slice1)[len(slice)-1])
    }
    
    
    • 结构体是值类型
    package main
    
    import "fmt"
    
    type Human struct {
      name string
      age int8
      sex byte
    }
    
    func main() {
      // 1.初始化 Human
      h1 := Human{"Steven", 35,1}
      fmt.Printf("h1: %T, %v, %p \n", h1,h1,&h1)
      fmt.Println("----------")
      // 2.复制结构体对象
      h2 := h1
      h2.name = "David"
      h2.age = 30
      fmt.Printf("h2修改后: %T, %v, %p \n", h2,h2,&h2)
      fmt.Printf("h1: %T, %v, %p \n", h1,h1,&h1)
      fmt.Println("----------")
      // 3.将结构体对象作为参数传递
      changeName(h1)
      fmt.Printf("h1: %T, %v, %p \n", h1,h1,&h1)
    }
    
    func changeName(h Human) {
      h.name = "Daniel"
      h.age = 13
      fmt.Printf("函数体内修改后: %T, %v, %p \n", h,h,&h)
    }
    
    
    
    • 结构体 深拷贝和浅拷贝 即值传递和引用传递
    package main
    
    import "fmt"
    
    type Dog struct {
      name string
      color string
      age int8
      kind string
    }
    
    func main() {
      // 1.实现结构体的深拷贝
      // struct 是值类型,默认的复制就是深拷贝
      d1 := Dog{"豆豆","黑色",2,"二哈"}
      fmt.Printf("d1: %T,%v,%p \n", d1,d1,&d1)
      d2 := d1 // 深拷贝
      fmt.Printf("d2: %T,%v,%p \n", d2,d2,&d2)
    
      d2.name = "毛毛"
      fmt.Println("d2 修改后 : ", d2)
      fmt.Println("d1:", d1)
      fmt.Println("-----------")
      // 2.实现结构体浅拷贝:直接复制指针地址
      d3 := &d1
      fmt.Printf("d3: %T,%v,%p \n", d3,d3,d3)
      d3.name = "球球"
      d3.color = "白色"
      d3.kind = "萨摩耶"
      fmt.Println("d3 修改后 : ", d3)
      fmt.Println("d1:", d1)
      fmt.Println("-----------")
      // 3.实心结构体浅拷贝:通过new() 函数来实例化对象
      d4 := new(Dog)
      fmt.Printf("d4: %T,%v,%p \n", d4,d4,d4)
    
      d4.name = "多多"
      d4.color = "棕色"
      d4.age = 1
      d4.kind = "八哥犬"
      d5 := d4
      fmt.Printf("d4: %T,%v,%p \n", d4,d4,d4)
      fmt.Printf("d5: %T,%v,%p \n", d5,d5,d5)
      fmt.Println("-----------")
      d5.color = "金色"
      d5.kind = "金毛"
      fmt.Println("d5修改后 : ", d5)
      fmt.Println("d4 : ", d4)
      fmt.Println("-----------")
    }
    
    
    • 匿名结构体
    package main
    
    import (
      "fmt"
      "math"
    )
    
    func main() {
      // 匿名函数
      res := func(a,b float64) float64 {
        return math.Pow(a,b)
      }(2,3)
      fmt.Println(res)
      // 匿名结构体
      addr := struct {
        province,city string
      }{"陕西省", "西安市"}
      fmt.Println(addr)
      cat := struct {
        name, color string
        age int8
      }{
        name : "绒毛",
        color: "黑白",
        age : 1,
      }
      fmt.Println(cat)
    }
    
    
    • 结构体的匿名字段
    package main
    
    import "fmt"
    
    type User struct {
      string
      byte
      int8
      float64
    }
    
    func main() {
      // 实例化结构体
      user := User{"Steven", 'm', 35, 177.5}
      fmt.Println(user)
      // 如果想一次输出姓名、年龄、身高、性别
      fmt.Printf("姓名:%s \n", user.string)
      fmt.Printf("身高:%.2f \n", user.float64)
      fmt.Printf("性别:%c \n", user.byte)
      fmt.Printf("年龄:%d \n", user.int8)
    }
    
    
    • 结构体嵌套模拟聚合关系
    package main
    
    import "fmt"
    
    type Address struct {
      province, city string
    }
    
    type Person struct {
      name string
      age int
      address *Address
    }
    
    func main() {
      // 模拟结构体对象之间的聚合关系
      p := Person{}
      p.name = "Steven"
      p.age = 35
      // 赋值方式1
      addr := Address{}
      addr.province = "北京市"
      addr.city = "海淀区"
      p.address = &addr
      fmt.Println(p)
      fmt.Println("姓名:", p.name)
      fmt.Println("年龄:", p.age)
      fmt.Println("省:", p.address.province)
      fmt.Println("市:", p.address.city)
      fmt.Println("-----------")
    
      // 修改Address对象的数据,是否会影响Person对象的数据? 会
      addr.city = "大兴区"
      fmt.Println("姓名:", p.name)
      fmt.Println("年龄:", p.age)
      fmt.Println("省:", p.address.province)
      fmt.Println("市:", p.address.city)
      fmt.Println("-----------")
      // 赋值方式2
      p.address = &Address{
        province: "陕西市",
        city: "西安市",
      }
      fmt.Println(p)
      fmt.Println("姓名:", p.name)
      fmt.Println("年龄:", p.age)
      fmt.Println("省:", p.address.province)
      fmt.Println("市:", p.address.city)
      fmt.Println("-----------")
    
    }
    
    
    • 结构体嵌套模拟继承关系
    package main
    
    import "fmt"
    
    type Person struct {
      name string
      age int
      sex string
    }
    
    type Student struct {
      Person
      schoolName string
    }
    
    func main() {
      // 1.实例化并初始化Person
      p1 := Person{"Steven", 35, "男"}
      fmt.Println(p1)
      fmt.Println("-----------")
      // 2.实例化并初始化Student
      // 写法1:
      s1 := Student{p1, "北航软件学院"}
      printInfo(s1)
      // 写法2
      s2 := Student{Person{"Json",30,"男"}, "北外外语院"}
      printInfo(s2)
      // 写法3
      s3 := Student{
        Person:Person{
          name: "Penn",
          age: 19,
          sex: "男",
        },
        schoolName: "北大元培学院",
      }
      printInfo(s3)
      // 写法4
      s4 := Student{}
      s4.name = "Daniel"
      s4.age = 12
      s4.sex = "男"
      s4.schoolName = "北京人大附中"
      printInfo(s4)
    }
    
    func printInfo(s1 Student) {
      fmt.Println(s1)
      fmt.Printf("%+v \n", s1)
      fmt.Printf("姓名:%s. 年龄:%d . 性别:%s . 学校 : %s \n", s1.name,s1.age,s1.sex,s1.schoolName)
      fmt.Println("-------------")
    
    }
    
    
    
    • 结构体嵌套时,可能存在相同的成员名,成员重名会导致成员名字冲突
    package main
    
    import "fmt"
    
    type A struct {
      a,b int
    }
    type B struct {
      a,d int
    }
    
    type C struct {
      A
      B
    }
    func main() {
      c := C{}
      c.A.a = 1
      c.B.a = 2 // 如果调用c.a = 3, 则会提示 "引起歧义的参数'
      c.b = 3
      c.d = 4
      fmt.Println(c)
    }
    
    • 方法与函数
    package main
    
    import "fmt"
    
    type Employee struct {
      name, currency string
      salary float64
    }
    
    func main() {
      emp1 := Employee{"Daniel", "$", 2000}
    
      emp1.printSalary()
      printSalary(emp1)
    }
    
    // printSalary() 方法
    func (e Employee) printSalary()  {
      fmt.Printf("员工姓名:%s . 薪资: %s%.2f\n", e.name,e.currency,e.salary )
    }
    // printSalary 函数
    func printSalary(e Employee)  {
      fmt.Printf("员工姓名:%s . 薪资: %s%.2f\n", e.name,e.currency,e.salary )
    }
    
    • 相同的方法名
    package main
    
    import (
      "fmt"
      "math"
    )
    
    type Rectangle struct {
      width, height float64
    }
    
    type Circle struct {
      radius float64
    }
    
    
    func main() {
    
      r1 := Rectangle{10,4}
      r2 := Rectangle{12,5}
      c1 := Circle{1}
      c2 := Circle{10}
    
      fmt.Println("r1的面积", r1.Area())
      fmt.Println("r2的面积", r2.Area())
      fmt.Println("c1的面积", c1.Area())
      fmt.Println("c2的面积", c2.Area())
    
    }
    
    func (r Rectangle) Area() float64  {
      return r.width * r.height
    }
    
    func (c Circle) Area() float64 {
      return c.radius * c.radius * math.Pi
    }
    
    
    • 指针作为接受者
    package main
    
    import "fmt"
    
    type Rectangle struct {
      width, height float64
    }
    
    func main() {
    
      r1 := Rectangle{5,8}
      r2 := r1
      // 打印对象的内存地址
      fmt.Printf("r1的地址: %p \n", &r1)
      fmt.Printf("r2的地址: %p \n", &r2)
    
      r1.setValue()
      fmt.Println("r1.height=", r1.height)
      fmt.Println("r2.height=", r2.height)
      fmt.Println("--------------")
      r1.setValue2()
      fmt.Println("r1.height=", r1.height)
      fmt.Println("r2.height=", r2.height)
      fmt.Println("--------------")
    }
    
    func (r Rectangle) setValue()  {
      fmt.Printf("setValue 方法中 r的地址: %p \n", &r)
      r.height = 10
    }
    
    func (r *Rectangle) setValue2()  {
      fmt.Printf("setValue2 方法中 r的地址: %p \n", r)
      r.height = 20
    }
    
    • 方法继承
    package main
    
    import "fmt"
    
    type Human struct {
      name,phone string
      age int
    }
    
    type Student struct {
      Human
      school string
    }
    
    type Employee struct {
      Human
      company string
    }
    
    func main() {
      s1 := Student{Human{"Daniel", "13013234***", 13}, "北京四中"}
      s2 := Employee{Human{"Steven", "15013234***", 28}, "搜狗"}
      s1.SayHi()
      s2.SayHi()
    }
    
    func (h *Human) SayHi()  {
      fmt.Printf("大家好,我是%s, 我%d岁, 我的联系方式是:%s \n", h.name,h.age, h.phone)
    }
    
    
    
    • 方法重写
    package main
    
    import "fmt"
    
    type Human struct {
      name,phone string
      age int
    }
    
    type Student struct {
      Human
      school string
    }
    
    type Employee struct {
      Human
      company string
    }
    
    func main() {
      s1 := Student{Human{"Daniel", "13013234***", 13}, "北京四中"}
      e1 := Employee{Human{"Steven", "15013234***", 28}, "搜狗"}
      s1.SayHi()
      e1.SayHi()
    }
    
    func (h *Human) SayHi()  {
      fmt.Printf("大家好,我是%s, 我%d岁, 我的联系方式是:%s \n", h.name,h.age, h.phone)
    }
    
    func (s Student) SayHi()  {
      fmt.Printf("大家好,我是%s, 我%d岁,我在%s上学, 我的联系方式是:%s \n", s.name,s.age,s.school,s.phone)
    }
    
    func (e Employee) SayHi()  {
      fmt.Printf("大家好,我是%s, 我%d岁,我在%s上班, 我的联系方式是:%s \n", e.name,e.age, e.company,e.phone)
    
    }
    
    
    • 接口
    package main
    
    import "fmt"
    
    type Phone interface {
      call()
    }
    
    type AndroidPhone struct {
    
    }
    
    type iPhone struct {
    
    }
    
    func (a AndroidPhone) call()  {
      fmt.Println("我是安卓手机,可以打电话了")
    }
    func (i iPhone) call()  {
      fmt.Println("我是苹果手机,可以打电话了")
    }
    
    func main() {
      // 定义接口类型的变量
      var phone Phone
      fmt.Printf("%T, %v, %p \n", phone, phone, &phone)
    
      phone = new(AndroidPhone)
      fmt.Printf("%T, %v, %p \n", phone, phone, &phone)
      phone.call()
      phone = AndroidPhone{}
      fmt.Printf("%T, %v, %p \n", phone, phone, &phone)
      phone.call()
    
      phone = new(iPhone)
      fmt.Printf("%T, %v, %p \n", phone, phone, &phone)
      phone.call()
      phone = iPhone{}
      fmt.Printf("%T, %v, %p \n", phone, phone, &phone)
      phone.call()
    
    }
    
    
    • duck typing
    package main
    
    import "fmt"
    
    type iSayHello interface {
      sayHello() string
    }
    
    type Duck struct {
      name string
    }
    
    type Person struct {
      name string
    }
    
    func (d Duck) sayHello() string {
      return d.name + "叫:嘎嘎嘎"
    }
    
    func (p Person) sayHello() string {
      return p.name + "说:嗨喽"
    }
    
    func main() {
      // 定义实现接口的对象
      duck := Duck{"大黄鸭"}
      person := Person{"小明"}
    
      fmt.Println(duck.sayHello())
      fmt.Println(person.sayHello())
      fmt.Println("----------")
    
      // 定义接口类型的变量
      var i iSayHello
      fmt.Printf("%T, %v, %p \n", i, i, &i)
    
      i = duck
      fmt.Printf("%T, %v, %p \n", i, i, &i)
      fmt.Println(i.sayHello())
    
      i = person
      fmt.Printf("%T, %v, %p \n", i, i, &i)
      fmt.Println(i.sayHello())
    
      
    
    }
    
    
    
    
    
    • 多态
    package main
    
    import "fmt"
    
    type Income interface {
      calculate() float64 // 计算收入总额
      source() string // 用来说明收入来源
    }
    
    // 固定账单项目
    type fixedBilling struct {
      projectName string // 工程项目
      biddedAmount float64 // 项目招标总额
    }
    
    // 定时生产项目(定时和材料项目)
    type timeAndMaterial struct {
      projectName string
      workHours float64 // 工作时长
      hourlyRate float64  // 每小时工资率
    }
    
    // 固定收入项目
    func (f fixedBilling) calculate() float64  {
      return f.biddedAmount
    }
    func (f fixedBilling) source() string {
      return f.projectName
    }
    
    // 定时收入项目
    func (t timeAndMaterial) calculate() float64  {
      return t.workHours * t.hourlyRate
    }
    
    func (t timeAndMaterial) source() string  {
      return t.projectName
    }
    
    // 通过广告点击获得收入
    type advertisement struct {
      adName  string
      clickCount int
      incomePerClick float64
    }
    
    func (a advertisement) calculate() float64  {
      return float64(a.clickCount) * a.incomePerClick
    }
    func (a advertisement) source() string  {
      return a.adName
    }
    
    func main() {
    
      p1 := fixedBilling{"项目1",5000}
      p2 := fixedBilling{"项目2",20000}
      p3 := timeAndMaterial{"项目3", 100,40}
      p4 := timeAndMaterial{"项目4", 80,50}
      p5 := advertisement{"广告1", 10000, 0.1}
      p6 := advertisement{"广告2", 20000, 0.05}
    
      ic := []Income{p1,p2,p3,p4,p5,p6}
    
      fmt.Println(calculateNetIncome(ic))
    
    }
    
    func calculateNetIncome(ic []Income) float64  {
      netIncome := 0.0
      fmt.Printf("类型:%T \n", netIncome)
      for _,income := range ic {
        fmt.Printf("收入来源:%s, 收入金额: %.2f \n", income.source(), income.calculate())
        netIncome += income.calculate()
      }
      return netIncome
    }
    
    
    
    
    • 空接口
    package main
    
    import "fmt"
    
    type A interface {
    
    }
    
    type Cat struct {
      name string
      agt int
    }
    
    type Person struct {
      name string
      sex string
    }
    
    func main() {
      var a1 A = Cat{"Mimi", 1}
      var a2 A = Person{"小明", "男"}
      var a3 A = "Learn golang "
      var a4 A = 100
      var a5 A = 3.14
      showInfo(a1)
      showInfo(a2)
      showInfo(a3)
      showInfo(a4)
      showInfo(a5)
    
      //1.fmt.Println 参数是空接口
      fmt.Println("println的参数是空接口,可以是接受任何数据类型", 100, 3.14, Cat{"喵喵",2})
      //2.定义map,value 是任何数据类型
      map1 := make(map[string]interface{})
      map1["name"] = "Daniel"
      map1["age"] = 13
      map1["height"] = 1.71
      fmt.Println(map1)
      fmt.Println("----------")
    
      //3.定义一个切片,其中存储任意数据类型
      slice1 := make([]interface{},0,10)
      slice1 = append(slice1, a1,a2,a3,a4,a5)
      fmt.Println(slice1)
    
    }
    
    func showInfo(a A) {
      fmt.Printf("%T, %v \n", a, a)
    }
    
    
    
    • 接口对象转型 (类型断言)
    package main
    
    import "C"
    import (
      "fmt"
      "math"
    )
    // 接口对象类型断言,根据对象不同做不同的反应
    //1.定义接口
    type Shape interface {
      perimeter() float64
      area() float64
    }
    
    //2.矩形
    type Rectangle struct {
      a,b float64
    }
    
    func (r Rectangle) perimeter() float64 {
      return 2 * (r.a + r.b)
    }
    
    func (r Rectangle) area() float64 {
      return r.a * r.b
    }
    
    //3.三角形
    type Triangle struct {
      a,b,c float64
    }
    
    func (t Triangle) perimeter() float64 {
      return t.a + t.b + t.c
    }
    
    func (t Triangle) area() float64 {
      // 海伦公式
      p := t.perimeter() / 2 // 半周长
      return math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
    }
    
    //4.圆形
    type Circle struct {
      radius float64
    }
    
    func (c Circle) perimeter() float64 {
      return 2 * math.Pi * c.radius
    }
    
    func (c Circle) area() float64 {
      return math.Pow(c.radius,2) * math.Pi
    }
    
    // 接口对象转型方式1 - 类型断言
    // instance, ok := 接口对象.(实际类型)
    func getType(s Shape) {
      if instance, ok := s.(Rectangle); ok {
        fmt.Printf("矩形:长度 %.2f,宽度 %.2f \t", instance.a, instance.b)
      } else if instance, ok := s.(Triangle); ok {
        fmt.Printf("三角形:三边分别是 %.2f, %.2f, %.2f \t", instance.a, instance.b, instance.c)
      } else if instance, ok := s.(Circle); ok {
        fmt.Printf("圆形:半径为 %.2f, \t", instance.radius)
      }
    }
    
    // 接口对象转型方式2
    // 接口对象.(type), 配合switch 和 case 语句使用
    func getType2(s Shape)  {
      switch instance := s.(type) {
      case Rectangle:
        fmt.Printf("矩形:长度 %.2f,宽度 %.2f \t", instance.a, instance.b)
      case Triangle:
        fmt.Printf("三角形:三边分别是 %.2f, %.2f, %.2f \t", instance.a, instance.b, instance.c)
      case Circle:
        fmt.Printf("圆形:半径为 %.2f, \t", instance.radius)
      }
    }
    
    func getResult(s Shape)  {
      getType(s)
      fmt.Printf("周长 %.2f,面积 %.2f \n", s.perimeter(),s.area())
    }
    
    func main() {
      var s Shape
      s = Rectangle{3,4}
      getResult(s)
      showInfo(s)
      s = Triangle{3,4,5}
      getResult(s)
      showInfo(s)
    
      s = Circle{1}
      getResult(s)
      showInfo(s)
    
      x := Triangle{3,4,5}
      fmt.Println(x)
    }
    func (t Triangle) String() string  { // 实现了系统接口,最后的打印部分会改变
      return fmt.Sprintf("Triangle对象,属性分别为:%.2f, %.2f, %.2f", t.a, t.b, t.c)
    }
    
    func showInfo(s Shape)  {
      fmt.Printf("%T, %v \n", s, s)
      fmt.Println("-----------")
    }
    
    

    相关文章

      网友评论

          本文标题:Go 面向对象编程

          本文链接:https://www.haomeiwen.com/subject/vzkpjktx.html