go 面向对象编程需要注意:
- Go的类型和值:
- 通过定义结构体类型的方式实现类似类的结构
- 没有构造方法,直接使用NewXXX()工厂方法
- 使用嵌入和聚合方式实现继承 ,推荐使用嵌入的方式
- 自由的结构体组合
//接口
type IPerson interface {
SetName(string)
GetName() string
}
//自定义函数
type MyFuncType func(int) int
//大杂烩结构体
type Something struct {
a int //基本数据类型
b []byte //切片
p Person //结构体
s *Student //指针
i IPerson //接口
f MyFuncType //自定义函数类型
any interface{} //任意类型
}
- 自定义方法更加灵活
//类型定义
type Preson struct {
name string
}
//类型方法,接收者为该类型的指针
func (p *Person) SetName(name string) {
p.name = name
}
//类型方法,接收者为该类型的值
func (p Person) GetName() string {
return p.name
}
//调用示例
p := new(Person)
//SetName()方法接收者为指针,使用指针类型或值类型去调用都可以
p.SetName("fun") //可以
*p.SetName("func") //指针取值后再去调用也可以。
//GetName()方法接收者为值类型,所以调用该方法只能为值
p.GetName() //不可以
*p.GetName() //可以
方法接收者一般有两种情况:
- 接收者为指针:允许该类型的指针和值调用该方法;
- 接收者为值:只允许该类型的值调用该方法。
一般无特殊需要,建议把接收者直接设置为指针类型
- 使用首字母大小写方式实现方法和变量的可见行
- 面向接口编程
package main
import "fmt"
type IAnimal interface {
shout()
cry()
}
type Human struct {
}
func (human *Human) shout() {
fmt.Println("Human shout....")
}
func (human *Human) cry() {
fmt.Println("Human cry ...")
}
type Bird struct {
}
func (bird *Bird) shout() {
fmt.Println("Bird shout....")
}
func (brid *Bird) cry() {
fmt.Println("Bird cry ...")
}
func main() {
var animal IAnimal
bird1 := new(Bird)
animal = bird1 // 任何实现接口的类型都可赋值给 抽象的接口
fmt.Println(animal)
}
- 使用空接口替代范性
package main
import "fmt"
// 父类
type Person struct {
name string
age int
}
func (person *Person) setName(name string) {
person.name = name
}
func (person *Person) getName()(string) {
return person.name
}
func (person *Person) setAge(age int) {
person.age = age
}
func (person *Person) getAge()(int) {
return person.age
}
// 继承
// 子类
type Student struct {
Person // 匿名字段嵌入类型
id int
score int
}
type Student1 struct {
P1 Person // 命名字段聚合类型
id int
score int
}
func (student *Student) getId() (int){
return student.id
}
func (student *Student) setId(id int) {
student.id = id
}
func (student *Student) getScore() (int) {
return student.score
}
func (student *Student) setScore(score int) {
student.score = score
}
// student重写setName()方法
func (student *Student) setName(name string) {
student.name = name
}
// student重写getName()方法
func (student *Student) getName() (string) {
return student.name
}
func (student *Student) showInfo() {
fmt.Println("I am a student...")
}
// 工厂方法
func NewPerson(name string, age int ) *Person {
p := new(Person)
p.setName(name)
p.setAge(age)
return p
}
func main() {
stu := Student{Person{"jack", 11}, 1001, 89}
per := Person{"renwoxing", 12}
per.setAge(32)
per.setName("renyingying")
fmt.Println(per.getName())
fmt.Println(per.getAge())
stu1 := new(Student1)
stu1.P1.setName("ssss") //聚合类型需要先访问属性名
stu2 := new(Student)
stu2.setAge(123) //嵌入类型可直接使用其内部方法或者内部属性
stu.setName("lisi")
fmt.Println(stu.getId(), stu.Person.getName(), stu.getScore(), stu.Person.getAge())
}