1. 抽象
2. 三大特性-封装
2.1 封装
2.2 封装的好处和实现
2.3 封装的实现步骤
package model
import "fmt"
type person struct {
Name string
age int //其它包不能直接访问..
sal float64
}
//写一个工厂模式的函数,相当于构造函数
func NewPerson(name string) *person {
return &person{
Name : name,
}
}
//为了访问age 和 sal 我们编写一对SetXxx的方法和GetXxx的方法
func (p *person) SetAge(age int) {
if age >0 && age <150 {
p.age = age
} else {
fmt.Println("年龄范围不正确..")
//给程序员给一个默认值
}
}
func (p *person) GetAge() int {
return p.age
}
func (p *person) SetSal(sal float64) {
if sal >= 3000 && sal <= 30000 {
p.sal = sal
} else {
fmt.Println("薪水范围不正确..")
}
}
func (p *person) GetSal() float64 {
return p.sal
}
package main
import (
"fmt"
"go_code/chapter11/encapsulate/model"
)
func main() {
p := model.NewPerson("smith")
p.SetAge(18)
p.SetSal(5000)
fmt.Println(p)
fmt.Println(p.Name, " age =", p.GetAge(), " sal = ", p.GetSal())
}
3. 三大特性-继承
3.1 继承
package main
import (
"fmt"
)
//编写一个学生考试系统
type Student struct {
Name string
Age int
Score int
}
//将Pupil 和 Graduate 共有的方法也绑定到 *Student
func (stu *Student) ShowInfo() {
fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n", stu.Name, stu.Age, stu.Score)
}
func (stu *Student) SetScore(score int) {
//业务判断
stu.Score = score
}
//给 *Student 增加一个方法,那么 Pupil 和 Graduate都可以使用该方法
func (stu *Student) GetSum(n1 int, n2 int) int {
return n1 + n2
}
//小学生
type Pupil struct {
Student //嵌入了Student匿名结构体
}
//显示他的成绩
//这时Pupil结构体特有的方法,保留
func (p *Pupil) testing() {
fmt.Println("小学生正在考试中.....")
}
//大学生
type Graduate struct {
Student //嵌入了Student匿名结构体
}
//显示他的成绩
//这时Graduate结构体特有的方法,保留
func (p *Graduate) testing() {
fmt.Println("大学生正在考试中.....")
}
func main() {
//当我们对结构体嵌入了匿名结构体使用方法会发生变化
pupil := &Pupil{}
pupil.Student.Name = "tom~"
pupil.Student.Age = 8
pupil.testing()
pupil.Student.SetScore(70)
pupil.Student.ShowInfo()
fmt.Println("res=", pupil.Student.GetSum(1, 2))
graduate := &Graduate{}
graduate.Student.Name = "mary~"
graduate.Student.Age = 28
graduate.testing()
graduate.Student.SetScore(90)
graduate.Student.ShowInfo()
fmt.Println("res=", graduate.Student.GetSum(10, 20))
}
3.2 继承深入
package main
import (
"fmt"
)
type A struct {
Name string
age int
}
func (a *A) SayOk() {
fmt.Println("A SayOk", a.Name)
}
func (a *A) hello() {
fmt.Println("A hello", a.Name)
}
type B struct {
A
Name string
}
func (b *B) SayOk() {
fmt.Println("B SayOk", b.Name)
}
func main() {
// var b B
// b.A.Name = "tom"
// b.A.age = 19
// b.A.SayOk()
// b.A.hello()
//上面的写法可以简化
//b.Name = "smith"
//b.age = 20
//b.SayOk()
//b.hello()
var b B
b.Name = "jack"
b.A.Name = "scott"
b.age = 100
b.SayOk() //B SayOk jack
b.A.SayOk() //A SayOk scott
b.hello() //A hello scott
}
package main
import (
"fmt"
)
type Goods struct {
Name string
Price float64
}
type Brand struct {
Name string
Address string
}
type TV struct {
Goods
Brand
}
type TV2 struct {
*Goods
*Brand
}
func main() {
var c C
//如果c 没有Name字段,而A 和 B有Name, 这时就必须通过指定匿名结构体名字来区分
//所以 c.Name 就会包编译错误, 这个规则对方法也是一样的!
c.A.Name = "tom" // error
fmt.Println("c")
//如果D 中是一个有名结构体,则访问有名结构体的字段时,就必须带上有名结构体的名字
//比如 d.a.Name
var d D
d.a.Name = "jack"
//嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值
tv := TV{Goods{"电视机001", 5000.99}, Brand{"海尔", "山东"},}
//演示访问Goods的Name
fmt.Println(tv.Goods.Name)
fmt.Println(tv.Price)
tv2 := TV{
Goods{
Price: 5000.99,
Name: "电视机002",
},
Brand{
Name: "夏普",
Address: "北京",
},
}
fmt.Println("tv", tv)
fmt.Println("tv2", tv2)
tv3 := TV2{&Goods{"电视机003", 7000.99}, &Brand{"创维", "河南"},}
tv4 := TV2{
&Goods{
Name: "电视机004",
Price: 9000.99,
},
&Brand{
Name: "长虹",
Address: "四川",
},
}
fmt.Println("tv3", *tv3.Goods, *tv3.Brand)
fmt.Println("tv4", *tv4.Goods, *tv4.Brand)
}
3.3 多重继承
4. 匿名字段是基本数据类型