哈喽,大家好,我是 Go大叔,专注分享 Go 语言知识,一起进入 Go 的大门。
大叔和身边一群大牛都无限看好 Go 语言,现在开始搞 Go 语言,过两年大概就是第一批吃螃蟹的人。
欢迎大家来到『Go 语言入门到精通』这个专栏,今天是专栏第 19 篇,大叔主要和大家分享一下 Go语言面向对象相关的知识点
。
面向对象是相对面向过程而言
面向对象和面向过程都是一种思想
面向过程
回想下前面我们完成一个需求的步骤:
在上面每一个具体步骤中我们都是参与者, 并且需要面对具体的每一个步骤和过程, 这就是面向过程最直接的体现
面向过程
面向对象
面向过程
面向对象
面向对象的核心就是对象,那怎么创建对象?
属性
和行为
Go语言中的类相当于图纸,用来描述一类事物。也就是说要想创建对象必须先有类
Go语言利用类来创建对象,对象是类的具体存在, 因此面向对象解决问题应该是先考虑需要设计哪些类,再利用类创建多少个对象
属性
和行为
。事物名称(类名):人(Person)
属性:身高(height)、年龄(age)
行为(功能):跑(run)、打架(fight)
属性
(状态特征)和行为
(能干什么事)的对象都可以抽像成为一个类##如何分析一个类
飞机
炮弹
装甲车
老王
热狗
草泥马
type Person struct {
name string // 人的属性
age int // 人的属性
}
// 人的行为
func (p Person)Say() {
fmt.Println("my name is", p.name, "my age is", p.age)
}
// 3.创建一个结构体变量
p1 := Person{"lnj", 33}
per.say()
p2 := Person{"zs", 18}
per.Say()
package demo
import "fmt"
var num1 int = 123 // 当前包可用
var Num1 int = 123 // 其它包也可用
type person struct { // 当前包可用
name string // 当前包可用
age int // 当前包可用
}
type Student struct { // 其它包也可用
Name string // 其它包也可用
Age int // 其它包也可用
}
func test1() { // 当前包可用
fmt.Println("test1")
}
func Test2() { // 其它包也可用
fmt.Println("Test2")
}
func (p person)say() { // 当前包可用
fmt.Println(p.name, p.age)
}
func (s Student)Say() { // 其它包也可用
fmt.Println(s.Name, s.Age)
}
将变化隔离
)。这样降低了数据被误用的可能 (提高安全性
和灵活性
)package model
import "fmt"
type Person struct { // 其它包也可用
name string // 当前包可用
age int // 当前包可用
}
func (p *person)SetAge(age int) {
// 安全校验
if age < 0 {
fmt.Println("年龄不能为负数")
}
p.age = age
}
package main
import (
"fmt"
"main/model"
)
func main() {
// 报错, 因为name和age不是公开的
//p := model.Person{"lnj", 18}
// 方式一
//p := model.Person{}
//p.SetAge(18)
//fmt.Println(p)
// 方式二
//p := new(model.Person)
//p.SetAge(18)
//fmt.Println(p)
}
继承性
普通继承(组合)
package main
import "fmt"
type Person struct {
name string
age int
}
type Student struct {
Person // 学生继承了人的特性
score int
}
type Teacher struct {
Person // 老师继承了人的特性
Title string
}
func main() {
s := Student{Person{"lnj", 18}, 99}
//fmt.Println(s.Person.name)
fmt.Println(s.name) // 两种方式都能访问
//fmt.Println(s.Person.age)
fmt.Println(s.age) // 两种方式都能访问
fmt.Println(s.score)
}
package main
import "fmt"
type Person struct {
name string // 属性重名
age int
}
type Student struct {
Person
name string // 属性重名
score int
}
func main() {
s := Student{Person{"zs", 18}, "ls", 99}
fmt.Println(s.Person.name) // zs
fmt.Println(s.name) // ls
//fmt.Println(s.Person.age)
fmt.Println(s.age) // 两种方式都能访问
fmt.Println(s.score)
}
package main
import "fmt"
type Object struct {
life int
}
type Person struct {
Object
name string
age int
}
type Student struct {
Person
score int
}
func main() {
s := Student{Person{Object{77}, "zs", 33}, 99}
//fmt.Println(s.Person.Object.life)
//fmt.Println(s.Person.life)
fmt.Println(s.life) // 三种方式都可以
//fmt.Println(s.Person.name)
fmt.Println(s.name) // 两种方式都能访问
//fmt.Println(s.Person.age)
fmt.Println(s.age) // 两种方式都能访问
fmt.Println(s.score)
}
package main
import "fmt"
type Object struct {
life int
}
type Person struct {
name string
age int
}
type Student struct {
Object
Person
score int
}
func main() {
s := Student{Object{77}, Person{"zs", 33}, 99}
//fmt.Println(s.Person.life)
fmt.Println(s.life) // 两种方式都可以
//fmt.Println(s.Person.name)
fmt.Println(s.name) // 两种方式都能访问
//fmt.Println(s.Person.age)
fmt.Println(s.age) // 两种方式都能访问
fmt.Println(s.score)
package main
import "fmt"
type Person struct {
name string
age int
}
// 父类方法
func (p Person)say() {
fmt.Println("name is ", p.name, "age is ", p.age)
}
type Student struct {
Person
score float32
}
func main() {
stu := Student{Person{"zs", 18}, 59.9}
stu.say()
}
package main
import "fmt"
type Person struct {
name string
age int
}
// 父类方法
func (p Person)say() {
fmt.Println("name is ", p.name, "age is ", p.age)
}
type Student struct {
Person
score float32
}
// 子类方法
func (s Student)say() {
fmt.Println("name is ", s.name, "age is ", s.age, "score is ", s.score)
}
func main() {
stu := Student{Person{"zs", 18}, 59.9}
// 和属性一样, 访问时采用就近原则
stu.say()
// 和属性一样, 方法同名时可以通过指定父类名称的方式, 访问父类方法
stu.Person.say()
}
猫: 猫-->动物
狗: 狗-->动物
男人 : 男人 -->人 -->高级动物
女人 : 女人 -->人 -->高级动物
package main
import "fmt"
// 1.定义接口
type Animal interface {
Eat()
}
type Dog struct {
name string
age int
}
// 2.实现接口方法
func (d Dog)Eat() {
fmt.Println(d.name, "正在吃东西")
}
type Cat struct {
name string
age int
}
// 2.实现接口方法
func (c Cat)Eat() {
fmt.Println(c.name, "正在吃东西")
}
// 3.对象特有方法
func (c Cat)Special() {
fmt.Println(c.name, "特有方法")
}
func main() {
// 1.利用接口类型保存实现了所有接口方法的对象
var a Animal
a = Dog{"旺财", 18}
// 2.利用接口类型调用对象中实现的方法
a.Eat()
a = Cat{"喵喵", 18}
a.Eat()
// 3.利用接口类型调用对象特有的方法
//a.Special() // 接口类型只能调用接口中声明的方法, 不能调用对象特有方法
if cat, ok := a.(Cat); ok{
cat.Special() // 只有对象本身才能调用对象的特有方法
}
}
一个人走的太慢,一群人才能走的更远。
最后,分享不易,喜欢大叔的文章,记得分享、点赞、在看
、三连支持!