go语言学习-面相对象

go 面相对象

只保留了组合(composition)这个最基础的特性

对象传递

Go语言和C语言一样,类型都是基于值传递的。要想修改变量的值,只能传递指针。

Go语言中的面向对象最为直观,也无需支付额外的成本。如果要求对象必须以指针传递, 这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。

只有在你需要修改对象的时候,才必须用指针

var a Integer = 1 //传入b=2
func (a *Integer) Add(b Integer) {
    *a += b // 执行方法后 a=3
}

// 如果传入的不是指针则方法外部a的值不变,相当于值传递


func (a Integer) Add(b Integer) { 
    a += b // 执行后a在外面不变 a=1 
}

值语义 和 引用语义

b=a
修改b,a值不变 值语义
修改b,a值改变 引用语义

go中数组为值语义

var a = [3]int{1, 2, 3}
var b = a
b[1]++
fmt.Println(a, b) //结果 [1 2 3] [1 3 3]

var a = [3]int{1, 2, 3}
var b = &a //b为a的引用
b[1]++
fmt.Println(a, *b) //结果 [1 3 3] [1 3 3]

或
var a = []int{1, 2, 3} // slice a 本身就是引用
var b = a //b的值直接就是引用
b[1]++
fmt.Println(a, *b) //结果 [1 3 3] [1 3 3]

go中四种引用类型

  • 数组切片(slice):指向数组(array)的一个区间。
  • map:极其常见的数据结构,提供键值查询能力。
  • channel:执行体(goroutine)间的通信设施。
  • 接口(interface):对一组满足某个契约的类型的抽象。

struct

初始化方式

  1. new : rect1 := new(Rect)
  2. rect2 := &Rect{} //rect2 引用,
  3. rect3 := Rect{} // rect3 值

指针方法和struct方法

  • struct方法类似于类方法, struct和实例都能用
  • 指针方法类似于对象方法,只有实现的实例可以用
package main

import ()
import "fmt"

type Dept struct {
	name     string
	building string
	floor    uint8
}

func (self Dept) Name() string {
	return self.name
}

func (self Dept) SetName(name string) {
	self.name = name
}

func (self *Dept) Relocate(building string, floor uint8) {
	self.building = building
	self.floor = floor
}

func main() {
	dept1 := Dept{name: "MySohu", building: "Media", floor: 7}
	dept1.Relocate("Media", 12) //实例调用指针方法
}

依据Go语言规范:

如果结构的实例x是"可被寻址的",且&x的方法集中包含方法m,则 x.m()为(&x).m()的速记(快捷方式)。

即:dept1是可被寻址的,且&dept1的方法集中包含方法Relocate(),则 dept1.Relocate()为&dept1.Relocate()的快捷方式。

组合

type Foo struct {
    ... //
    Base
}

//也有形如下面这种,只是Foo创建实例的时候,需要外部提供一个Base类 实例的
type Foo struct {
    ... //
    *Base
}
//这种方式可以很容易的借到定义类型的方法

eg:

type Job struct {
    Command string
    *log.Logger
}

func (job *Job)Start() {
    //借用log.Logger的方法,实际还是使用原有log.Logger的方法,因此不能访问到Job中的其他属性
    job.Log("starting now...") 
    ... //做事情
    job.Log("started.")
}


//匿名组合类型相当于以其类型名称(去掉包名部分) 作为成员变量的名字。按此规则,Y类型中就相当于存在两个名为Logger的成员,虽然类型不同。 因此,我们会收到编译错误。
type Logger struct {
    Level int
}
type Y struct {
    *Logger
    Name string
    *log.Logger
}

//这个编译错误并不是一定会发生的。 如这两个Logger在定义后再也没有被用过,那么编译器将直接  忽略掉这个冲突问题,直到开发者开始使用其中的某个Logger。

转载于:https://my.oschina.net/solate/blog/714471

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值