接口与结构体
type Person interface {
Eat()
Act()
}
type Student struct {
Name string
}
type Teacher struct {
Name string
}
// 学生实现接口函数
func (s *Student) Eat() {
fmt.Printf("student %s eat\n", s.Name)
}
func (s *Student) Act() {
fmt.Printf("student %s act study\n", s.Name)
}
// 老师实现接口函数
func (t *Teacher) Eat() {
fmt.Printf("teacher %s eat\n", t.Name)
}
func (t *Teacher) Act() {
fmt.Printf("teacher %s act teach\n", t.Name)
}
func main() {
// 创建人类接口
var person Person
// 创建学生
student := &Student{Name: "高启强"}
// 创建老师
teacher := &Teacher{Name: "安欣"}
person = student
person.Eat()
person.Act()
person = teacher
person.Eat()
person.Act()
/*
student 高启强 eat
student 高启强 act study
teacher 安欣 eat
teacher 安欣 act teach
*/
}
代码可以看出,定义一个接口类型Person和二个结构体类型Student、Teacher,创建实例赋值给接口变量。接口变量调用同一个方法调用的却是每个实例自己实现的方法。
interface 让 golang 编码更灵活、易扩展,使得 Go 拥有了面向对象多态的特性。
接口里面包含的都是方法,不带有属性。实现了该接口的任何对象都可以给对应的接口类型变量赋值。
结构体嵌套结构体
// 定义人类结构
type Person struct {
Name string
}
// 创建人类的方法
func (p *Person) MyName() {
fmt.Printf("person my name is [%s]\n", p.Name)
}
// 定义学生结构体
type Student struct {
Person
}
type Teacher struct {
Person
}
// 创建老师的方法
func (t *Teacher) MyName() {
fmt.Printf("teacher my name is [%s]\n", t.Name)
}
func main() {
person := Person{Name: "高启兰"}
person.MyName()
student := &Student{Person: person}
student.MyName()
teacher := &Teacher{Person: person}
teacher.MyName()
/*
person my name is [高启兰]
person my name is [高启兰]
teacher my name is [高启兰]
*/
}
父类Person衍生出Student与Teacher,子类继承了父类的属性与方法,方法可以直接调用,子类也可以重写父类方法。
结构体嵌套接口
type People interface {
MyName()
}
// 定义人类结构
type Person struct {
Name string
}
// 创建人类的方法
func (p *Person) MyName() {
fmt.Printf("person my name is [%s]\n", p.Name)
}
// 定义学生结构体
type Student struct {
People
}
type Teacher struct {
People
Name string
Subject string
}
// 创建老师的方法
func (t *Teacher) MyName() {
fmt.Printf("teacher my name is [%s] teach [%s]\n", t.Name, t.Subject)
}
func main() {
// 创建人类实例
person := Person{Name: "高启兰"}
person.MyName()
// 创建学生实例,People接口用person初始化
student := &Student{People: &person}
student.MyName()
// 创建老师实例,再将teacher实例赋值给接口
teacher := &Teacher{Name: "黄瑶", Subject: "化学"}
var people People = teacher
people.MyName()
/*
person my name is [高启兰]
person my name is [高启兰]
teacher my name is [黄瑶] teach [化学]
*/
}
Student实例里面接口用Person实例初始化,调用有接口方法为接口实例对象的MyName方法。该方法可以被Student重写,调用即为重写后的方法
Teacher实例中接口不初始化即为nil,实现MyName方法之后可以将Teacher实例估值给People接口,调用MyName为Teacher自己实现的方法。
个人观点
个人认为可以无视结构体内嵌套的接口,若需要用实现接口方法的实例初始化即可,不需要自己实现接口方法,可以再次赋值给接口。