美文网首页
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