Golang采用嵌入字段来实现继承,由于实现上存在多种可能,这里进行测试,看看Golang的设计思路。
待考察的问题包括:
嵌入的是结构,还是指针?
嵌入部分是匿名字段,还是命名字段?
方法是传值,还是传指针?
最终结论:
可以嵌入字段,也可以嵌入指针,其特性吻合惯性思维
无论字段是否指针,无论方法的接收者是否指针,在字段引用时都不区分指针
以下是测试过程
一共4组不同情形的测试
结构中有另一个结构,这是最简单的情形
结构中有一个匿名结构,测试用类型代替字段名,或直接引用
结构中有指针指向另一个结构
结构中有匿名指针指向另一个结构
每组测3个项目
继承后的引用
传值方法的继承
传指针方法的继承
故一共12个测试
第1组测试
结构中有另一个结构,这是最简单的情形
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person Person
// 有另一个字段
school
string
}
func
main() {
anna := new(Student)
anna.person.name =
"Anna"
anna.person.tel =
"12345678"
//anna.school = "mit"
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, anna.person.name, anna.person.tel)
}
第1.1组测试
结构中有另一个结构,这是最简单的情形
测试这种情况下方法的继承
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person Person
// 有另一个字段
school
string
}
//在person上面定义了一个传值的method
func
(p Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.person.name =
"Anna"
anna.person.tel =
"2345678"
//anna.school = "mit"
// anna.Hello() // 这是不行的,非匿名字段不能直接引用
anna.person.Hello()
//fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}
结论:
如果字段没有匿名,则相当于中间隔了一层,不能跨越去引用
第1.2组测试
结构中有另一个结构,这是最简单的情形
测试这种情况下方法的继承
但是定义传指针的method
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person Person
// 有另一个字段
school
string
}
//在person上面定义了一个传指针的method
func
(p * Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.person.name =
"Anna"
anna.person.tel =
"345678"
//anna.school = "mit"
// anna.Hello() // 这是不行的,非匿名字段不能直接引用
anna.person.Hello()
//fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}
结论:
没有问题,method传值或传指针没有区别
第2组测试
结构中有一个匿名结构,测试用类型代替字段名,或直接引用
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
Person
// 有一个匿名字段
school
string
}
func
main() {
anna := new(Student)
anna.Person.name =
"Anna"
// 用类型代替字段名
anna.tel =
"123456789"
// 或者直接引用
//anna.school = "mit"
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, anna.Person.name, anna.tel)
}
第2.1组测试
结构中有一个匿名结构
测试这种情况下方法的继承
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
Person
// 有另一个字段
school
string
}
//在person上面定义了一个传值的method
func
(p Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.Person.name =
"Anna"
anna.tel =
"2345"
//anna.school = "mit"
anna.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
//fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}
结论:匿名字段,相当于匿名结构直接嵌入,在同一层面
第2.2组测试
结构中有一个匿名结构
测试这种情况下方法的继承
但是定义传指针的method
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
Person
// 有另一个字段
school
string
}
//在person上面定义了一个传指针的method
func
(p * Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.Person.name =
"Anna"
anna.tel =
"345"
//anna.school = "mit"
anna.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
//fmt.Printf( "My name is %s, and my tel number is %s\n", anna.person.name, anna.person.tel)
}
结论:
传指针无影响
第3组测试
结构中有指针指向另一个结构
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person * Person
// 指针指向一个字段
school
string
}
func
main() {
anna := new(Student)
anna.person = new(Person)
// 必须,否则panic
anna.person.name =
"Anna"
anna.person.age = 22
anna.person.tel =
"12345"
anna.school =
"mit"
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, anna.person.name, anna.person.tel)
}
第3.1组测试
结构中有指针指向另一个结构
测试方法的继承
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person * Person
// 指针指向一个字段
school
string
}
//在person上面定义了一个传值的method
func
(p Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.person = new(Person)
anna.person.name =
"Anna"
anna.person.tel =
"234567"
anna.person.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
}
结论:
非常正常的使用
第3.2组测试
结构中有指针指向另一个结构
测试方法的继承
但是定义传指针的method
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
person * Person
// 指针指向一个字段
school
string
}
//在person上面定义了一个传指针的method
func
(p * Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.person = new(Person)
anna.person.name =
"Anna"
anna.person.tel =
"345678"
anna.person.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
}
结论:
指针无影响
第4组测试
结构中有匿名指针指向另一个结构
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
* Person
// 匿名指针指向一个字段
school
string
}
func
main() {
anna := new(Student)
anna.Person = new(Person)
anna.Person.name =
"Anna"
//anna.Person.age = 22
anna.tel =
"123"
//anna.school = "mit"
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, anna.Person.name, anna.tel)
}
结论:
anna.Person = new(Person) 居然也行
匿名相当于直接嵌入,在同一层面
Golang似乎是尽量识别,如果有字段名,包括指针,则必须用字段名,如果是匿名,则可用匿名字段的类型
第4.1组测试
结构中有匿名指针指向另一个结构
测试方法的继承
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
* Person
// 匿名指针指向一个字段
school
string
}
//在person上面定义了一个传值的method
func
(p Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.Person = new(Person)
anna.Person.name =
"Anna"
anna.tel =
"23456789"
anna.Person.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
anna.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
}
结论
在同一层面,当然加上匿名指针也可
第4.2组测试
结构中有匿名指针指向另一个结构
测试方法的继承
但是定义传指针的method
package
main
import
"fmt"
type
Person
struct
{
name
string
age
int
tel
string
}
type
Student
struct
{
* Person
// 匿名指针指向一个字段
school
string
}
//在person上面定义了一个传指针的method
func
(p * Person) Hello() {
fmt.Printf(
"My name is %s, and my tel number is %s\n"
, p.name, p.tel)
}
func
main() {
anna := new(Student)
anna.Person = new(Person)
anna.Person.name =
"Anna"
anna.tel =
"34"
anna.Person.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
anna.Hello()
// 匿名字段,相当于匿名结构直接嵌入,在同一层面
}
结论:
一样使用