(八)Go语言面向对象-结构体和方法(继承,封装,内嵌)

 面向对象


 概述:go语言仅支持封装,不支持继承和多态,所以go语言没有class,只有struct

下面我将详细整理下struct的用法,通过代码将学习的知识巩固下,如有错误,请指出!!!

一.结构体和方法

type TreeNode struct {
	value       int
	Left, Right *TreeNode
}

func main() {
	var root TreeNode
	root = TreeNode{value: 3}
	root.Left = &TreeNode{}
	root.Right = &TreeNode{5, nil, nil}
	root.Right.Left = new(TreeNode)

	nodes := []TreeNode{
		{value: 3, Left: &root},
		{},
		{6, nil, &root},
	}
    
    // 下面这个定义大家细品 
    var nillRoot *TreeNode
    fmt.Println(nillRoot) // 输出结果是:<nil>
    doRoot := new(TreeNode)
    fmt.Println(doRoot) // 输出结果是:&{0 <nil> <nil>}
}
  •  不论地址还是结构体本身,一律使用.来访问成员
// 工厂函数
func createNode(value int) *TreeNode {
	return &TreeNode{Value: value}
}
root.Right.Left = createNode(2)
  • 使用自定义工厂函数
  • 注意返回了局部变量的地址
  • 结构创建在堆上还是栈上? 答案:不需要知道(有可能在堆上也有可能在栈上,由go的垃圾回收机制清理)
// 为结构定义方法
func (node TreeNode) print() {
	fmt.Println(node.Value)
}

func (node *TreeNode) setValue(value int) {
	node.Value = value
}
  • 显示定义和命名方法接受者
  • 只有使用指针才可以改变结构内容,如setValue方法
  • nil指针也可以调用方法
  • 值接收者和指针接收者(1.要改变内容必须使用指针接收者2.结构过大也要考虑使用指针接受者)

二 .包和封装

   封装的特点:

  • 名字一般使用CamelCase
  • 首字母大写public 针对 包
  • 首字母小写pravite 针对 包

   包的特点:

  • 每个目录一个包(包名不需要和目录名一致)
  • main包包含可执行入口
  • 为结构定义的方法必须放在一个包内
  • 可以是不同的文件

三.扩展已有的类型

    如何扩充系统类型或者别人的类型?

  • 定义别名(自己定义一个包)
  • 使用组合(如下代码所示)
// 使用组合的方式
type myTreeNode struct {
	node *tree.Node
}

func (myNode *myTreeNode) postOrder() {
	if myNode == nil || myNode.node == nil {
		return
	}
	left := myTreeNode{myNode.node.Left}
	left.postOrder()
	right := myTreeNode{myNode.node.Right}
	right.postOrder()
	myNode.node.Print()
}

func main() {
	var root tree.Node
	root = tree.Node{Value: 3}
	root.Left = &tree.Node{}
	root.Right = &tree.Node{5, nil, nil}
	root.Left.Right = &tree.Node{}
	root.Right.Left = new(tree.Node)
	root.Right.Left = tree.CreateNode(2)
	root.Left.Right.SetValue(4)

	// 使用组合的方式
	root.Traverse()
	fmt.Println()
	myroot := myTreeNode{&root}
	myroot.postOrder()
	// myTreeNode{&root}.postOrder() // 这样写会报错:只有变量才能拿地址

}
  • 使用内嵌方式扩展已有类型 (有点类似继承)
// 内嵌类型扩展
type myTreeNode struct {
	*tree.Node // Embedding 内嵌
}

func (myNode *myTreeNode) postOrder() {
	if myNode == nil || myNode.Node == nil {
		return
	}
	left := myTreeNode{myNode.Left}
	left.postOrder()
	right := myTreeNode{myNode.Right}
	right.postOrder()
	myNode.Print()
}

// 类似重载
func (myTreeNode *myTreeNode) Traverse() {
	fmt.Println("this is shadowed")
}

func main() {
	// 使用内嵌方式
	root := myTreeNode{&tree.Node{Value: 3}}
	root.Left = &tree.Node{}
	root.Right = &tree.Node{5, nil, nil}
	root.Left.Right = &tree.Node{}
	root.Right.Left = new(tree.Node)
	root.Right.Left = tree.CreateNode(2)
	root.Left.Right.SetValue(4)
	// root.postOrder()
	// 原有的
	root.Node.Traverse()
	//重载的
	root.Traverse()
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值