在说Go的继承之前,先谈一下C语言的继承,在c中,通过结构体来实现。
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char *name;
int age;
}Person;
typedef struct{
Person parent;
int grade;
int class;
}Student;
Student * create_student(int grade,int class,const char* name,int age)
{
Student *p = (Student *)malloc(sizeof(Student));
p->class = class;
p->grade = grade;
return p;
}
void test(Student *stu)
{
Person *p = (Person *)stu;
p->name = "world";
p->age = 18;
stu->grade = 5;
printf("person address: %p\n",p);
}
int main()
{
Student *stu = (Student *)malloc(sizeof(Student));
test(stu);
printf("student parent: %p student: %p\n",&(stu->parent),stu);
free(stu);
return 0;
}
可以看到上面的例子中,Student 这个结构体中有一个Person parent 的变量,而且这个变量必须写在第一行,这样Student 主变向继承自Person 了,因为在Student 初始化时,它的地址和parent 的地址是相同的,指向同一位置。
这就可以解释在test 函数中,为什么可以把Student 指针强转成Person 指针了,就因为它们的地址是指向同一个地址。
上面的例子最终输出的都是同一个地址。
下面我们再来看Go语言中的继承,其实和c语言看上去有一点相似,毕竟都是通过结构体来实现的。
package main
import "fmt"
type person struct {
name string
age int
}
func (p *person) say() {
fmt.Println(p.name)
p.name = "李四"
}
type student struct {
person
grade int
}
func main() {
fmt.Print("hello world\n")
var s student = student{
person: person{
name: "张三",
},
grade: 1,
}
s.name = "王五"
s.say()
fmt.Println(s.name)
}
可以看到在student 这个结构体中,有一个person 的匿名类型,我们可以看到s 变量初始化时给name赋值张三 ,下面一行直接又改成了王五 ,而name 属性是person 结构体中的属性,但是此是s 却可以给name 赋值,并且还可以调用person 的say 方法,说明student 继承了person 的属性和方法。
不过要注意赋值的方式,特别是变量声明时赋值的方式 。
|