golang学习路径03面向对象封装继承多态
Posted 如何在5年薪百万
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang学习路径03面向对象封装继承多态相关的知识,希望对你有一定的参考价值。
六、面向对象
- 仅支持封装,不支持继承和多态
- go语言没有class有struct
- go没有构造器,可以使用工厂方法代替
通过面向对象学习struct和interface
6.1 type关键字
定义一种新的数据类型
func testType()
// type代表定义一种新的类型,这里等同于int类型的别名。
// 一般用来定义结构体或者接口
type number int
var b number =10
fmt.Println(b)
6.2 struct定义和初始化
结构体可以包含多个类型的组合,接近java中的类对象
定义stuct
type treeNode struct
value int
left, right *treeNode
var root treeNode
//创建对象的方法
//1 指定单个参数
root = treeNodevalue: 3
//2. 使用指针创建
root.right = &treeNode
//3. 指定全部参数
root.left = &treeNode5, nil, nil
//4. new关键字创建
root.right.left = new(treeNode)
//5. 工厂模式创建
root.left.right = treeNodeFactory(2)
//6. 数组定义可以简写
nodes := []treeNode
value: 3,
,
6, nil, nil,
方法属性
- 比普通func多了一个(接收对象 类型),其他和普通函数没有区别
- 通过指针实现值传递
- nil指针可以安全使用,调用方法
//给tree定义一个方法print
//小括号代表this指向括号内接收的对象,node指向对象引用
func (node treeNode) print()
fmt.Println(node.value)
//set pointer实现引用传递
func (node *treeNode) setValue(val int)
node.value = val
值接收 vs 指针接收
- 要改变内容必须使用指针接收
- 结构过大也是用指针接收
- 如果已经使用了指针接收,最好保持一致
package main
import "fmt"
func main()
p1:=People
name: "matthew",
age: 33,
gender: false,
p1.showPeople()
p1.setName("lisi")
fmt.Println("getName",p1.getName())
func testType()
// type代表定义一种新的类型,这里等同于int类型的别名。
// 一般用来定义结构体或者接口
type number int
var b number =10
fmt.Println(b)
// 定义一个people的结构体
type People struct
name string
age int
gender bool
//get 方法
func (this *People)getName() string
return this.name
//set 方法,struct是值传递,所以必须使用指针达成引用传递效果
func (this *People)setName(name string)
this.name=name
//string 方法
func(this *People)showPeople()
fmt.Println(this)
struct的方法无论使用值接收,还是指针接收,调用方式无变化
6.3 接口Interface
- 接口是万能类型,基础类型如int、struct都实现了interface,所以interface可以接收任何类型。
- 接口实现是隐式的,实现接口中的所有方法就代表实现了改接口
duck typing:描述事物外部行为而非内部结构,从使用者角度看待。go属于结构化类型系统,接近duck typing
接口定义
- 接口定义了一个方法名字,返回值和参数,不需要方法体
- 接口可以作为参数在函数中传递
- 貌似不能有属性,只能有方法
//接口定义一个方法类型
type Retriver interface
Get(string) string
//函数中使用接口作为参数传递
func download(r Retriver, url string) string
return r.Get(url)
接下来定义接口的实现
- 只要实现了接口的方法就默认实现了接口
- 实现了接口就具备了多态的可能
定义一个type用于mock请求返回一个字符串
package mock
type Retriver struct
Content string
// struct实现了接口的方法,也就实现了接口
func (r Retriver) Get(url string) string
return r.Content
定义一个类似的接口,真实的获取网页的地址
package real
import (
"net/http"
"net/http/httputil"
"time"
)
type Retriver struct
UserAgent string
Timerout time.Duration
func (r Retriver) Get(s string) string
get, err := http.Get(s)
if err != nil
panic(err)
response, err := httputil.DumpResponse(get, true)
defer get.Body.Close()
if err != nil
panic(err)
return string(response)
interface万能类型
基础类型int,flat,stuct等都实现了interface,所以后者可以作为万能类型
func printVal(val interface)
fmt.Println(val)
type Book struct
name string
func main()
//interface可以作为万能类型
book:=Bookname: "MyHeart"
printVal(100)
printVal("string")
printVal(3.14)
printVal(book)
判断接口类型
- 通过
变量.(类型)
判断是否是指定类型,ok代表true - 通过printF %T打印实际类型
func printVal1(val interface)
value,ok:=val.(string) //类型判断,是否是string类型,ok代表是string
if ok
fmt.Println(value)
else
fmt.Printf("val is not string,type is %T \\n",val)
func main()
fmt.Println("-------")
//接口类型判断
printVal1(100)
printVal1("hello")
- 表示任何类型: interface
- 类型判断 type Assertion
- 类型选择 type Swtich
golang系统接口参考
- Stringer 格式化输出
- Reader
- Writer
6.3 子类继承父类
- 在子类定义时,写入父struct名称,即继承了父类
- 子类可以添加新的属性和方法
- 子类可以直接调用父类的属性和方法
- 可见性仅有首字母大小写控制
package main
import "fmt"
/**
子类继承父类
*/
func main()
student:=Student
People: People
name:"xiaowang",
age:9,
gender:true,
,
grade: 3,
student.ShowStudent()
fmt.Println("people name",student.name) //获取父类属性
fmt.Println("student grade",student.grade) //获取父类属性
student.Eating() //调用父类方法
student.study() //调用子类方法
type Student struct
People //子类Student继承父类的属性和方法
grade int //年级
//子类增加新的方法
func (s *Student) study()
fmt.Println("student is studying")
func (s *Student)ShowStudent()
fmt.Println(s)
// 定义一个people的结构体
type People struct
name string
age int
gender bool
//get 方法
func (this *People)GetName() string
return this.name
//set 方法,struct是值传递,所以必须使用指针达成引用传递效果
func (this *People)setName(name string)
this.name=name
func (this *People) Eating()
fmt.Println("People is eating")
//string 方法
func(this *People) ShowPeople()
fmt.Println(this)
6.4 多态 interface
golang中的多态概念上和java完全一致,需满足三个条件
- 定义父类对象,go中必须是interface
- 定义子类struct,实现父类全部方法(否则不满足继承条件)
- 父类对象(pointer指针变量)指向(引用)子类变量地址
仔细研究下面代码,体会多态的含义
package main
import "fmt"
/**
1. 定义父类接口
*/
type Animal interface
GetColor() string
Eat()
Sleep()
/**
2.1 定义子类Dog,必须实现所有方法
*/
type Dog struct
color string
func (dog *Dog)Eat()
fmt.Println("dog is eating")
func (dog *Dog) Sleep()
fmt.Println("dog is sleeping")
func (dog *Dog)GetColor() string
return "dog "+ dog.color
/**
2.2 定义子类Cat,同上。两者的方法有不同实现
*/
type Cat struct
color string
func (cat *Cat)Eat()
fmt.Println("cat is eating")
func (cat *Cat)Sleep()
fmt.Println("cat is sleeping")
func (cat *Cat)GetColor() string
return "cat " + cat.color
//多态传参,根据传入的引用类型调用对应方法
func showColor(animal Animal)
fmt.Println(animal.GetColor())
func main()
// 3. 父类指向子类对象
var animal Animal //父类指针
animal=&Catcolor: "white"
animal.Sleep() //cat is sleeping
showColor(animal)
fmt.Println("-----------")
animal=&Dogcolor: "yellow"
showColor(animal)
animal.Eat() //dog is eating
以上是关于golang学习路径03面向对象封装继承多态的主要内容,如果未能解决你的问题,请参考以下文章