Go系列(六):面向对象

结构体和方法

  • go语言仅支持封装,不支持继承和多态
  • go语言没有class 只有struct
  • go语言没有构造函数的说法
  • 结构创建在堆上还是栈上? 不需要知道
  • 在调用的时候,编译器很聪明的,要值还是指针,编译器会帮我们转换
package main

import "fmt"

type treeNode struct {
	value       int
	left, right *treeNode
}
// 给结构定义方法
// (node treeNode):接受者 这个参数也是传值
// 和普通函数没有区别
func (node treeNode) print(){
	fmt.Println(node.value)
}

// node是传值,所以修改是没有作用的
func (node treeNode) setValue(value int){
	node.value = value // 指针的话,可以赋值
}

// 改成指针
// 只有使用指针才可以改变结构内容
func (node *treeNode) setValuePtr(value int){
	node.value = value
}

// 使用自定义工厂函数
func createNode(value int) *treeNode {
	// 返回了局部变量的地址
	return &treeNode{value: value}
}

func main() {
	var root treeNode
	fmt.Println(root) //{0 <nil> <nil>}

	// 赋值
	root = treeNode{value: 3}
	root.left = &treeNode{}
	root.right = &treeNode{5, nil, nil}
	node := []treeNode{
		{value: 3},
		{},
		{6, nil, &root},
	}// [{3 <nil> <nil>} {0 <nil> <nil>} {6 <nil> 0xc00000c080}]
	root.right.left = new(treeNode)


	root.left.right = createNode(2)
	root.setValue(5)
	fmt.Println(root)//{3 0xc00000c0c0 0xc00000c0e0}
	root.setValuePtr(6)
	fmt.Println(root) // {6 0xc0000a6060 0xc0000a6080}

	fmt.Println(node)
	root.print()
	// nil指针可以调用方法 但是会报错,
	var pRoot *treeNode
	pRoot.setValue(1)
}
值接受者vs指针接受者
  • 要改变内容必须使用指针接受者
  • 结构过大考虑指针接受者
  • 一致性:如有指针接受者,最好使用指针接受者
  • 值接受者是go语言特有的

封装

  • 名字使用CamelCase
  • 首字母大写:public
  • 首字母小写:private
  • 大小写是针对包来讲,仅对包管理有效

  • 每个目录(不含子目录)一个包
  • 包名可以和目录名不一样
  • main包包含可执行入口,main函数必须在main包里才可以执行
  • 为结构定义的方法必须放在同一个包内,但是可以不同的文件

扩展已有类型

  • 如何系统的扩展其他人写的类型,
    • 定义别名
    • 使用组合
    • 使用内嵌
// 使用组合
type myTreeNode struct {
	node *Node //包含原有要扩展的类型,然后在他的基础上,扩展自己想要的功能
}

func (myNode *myTreeNode) postOrder(){
	if myNode ==nil{
		return
	}
	// 遍历左子树
	lNode := myTreeNode{myNode.node.Left}
	lNode.postOrder()

	// 遍历右子树
	rNode := myTreeNode{myNode.node.Right}
	rNode.postOrder()
	
	// 遍历自己
	myNode.node.Print()
	
}



// 使用别名扩展类型
type Queue []int

func (q *Queue) Push(v int) {
	*q = append(*q, v)
}

func (q *Queue) Pop()  int{
	v:=(*q)[0]
	*q = (*q)[1:]
	return v
}


// 使用内嵌
// 使用内嵌可以省略很多代码
 使用内嵌 实质上是省略成员名 将成员变量从包中带过来(包括方法和成员变量)
type myTreeNode struct {
	*Node  // 内嵌方法
}

func (myNode *myTreeNode) postOrder(){
	if myNode ==nil{
		return
	}
	// 遍历左子树
	//lNode := myTreeNode{myNode.Node.Left} 类型的最后一个点的后面是他的名字
	lNode := myTreeNode{myNode.Left} // 也可以直接省略
	lNode.postOrder()

	// 遍历右子树
	rNode := myTreeNode{myNode.Right}
	rNode.postOrder()

	// 遍历自己
	myNode.Print()

}

// 使用内嵌之后,当本身的方法与包中的方法名称一样时,为了区别,调用方法不同
// 这个方法会让Node的方法隐藏起来,要调用的话
// myTree.Print() //调用myTreeNode的Print方法
// myTree.Node.Print() // 调用Node的Print方法
func (myTree *myTreeNode) Print(){
	//。。。。
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值