golang中interface的一些语法缺陷的改进

GO语言有一个独门秘技:interface,是大师们对OOP的经典诠释,是对传统OOP思维的一个巧妙颠覆。

既优雅地实现运行时多态,又不需要像C++那样显式申明,完美的解除了类型实现跟接口调用之间的耦合。

Go语言的主要设计者之一Russ Cos曾经说过,如果只能选择一个Go语言的特性移植到其他语言中,他会选择接口。可见接口在GO中的地位,及其对GO这门语言所带来的活力。

Russ Cos: interface https://research.swtch.com/interfaces

Ian Lance Taylor: go interface https://www.airs.com/blog/archives/277

然而,由于GO的interface定义与具体实现类型之间不需要显式申明,只需要实现类实现interface定义的所有method即可赋值。

然而这种宽松的约定,却带来一些逻辑上的麻烦。

这里有个例子:https://github.com/vipally/glab/blob/master/lab12/walk_test.go

有两个包filepath和pet都定义了一个Walker接口,并实现了相应的实现类型。

但是巧的是这两个Walker接口的定义都是一样的

type Walker interface {
    Walk()
}

但是显然,pet.Walker是想实现所有pet的“走路”行为

而filepath.Walker是想实现目录的“遍历”功能

然而,虽然两个接口的定义是一样的,但是期望的行为应该是不一样的。

从逻辑上说,用filepath.Walker调用pet.Dog.Walk()应该是一个错误的行为,然而从GO的语法上看,这种操作居然是合法的:

	
var petWalker pet.Walker
var filepathWalker filepath.Walker
println("call by pet.Walker:")
petWalker = &pet.Dog{}
petWalker.Walk()
petWalker = &pet.Cat{}
petWalker.Walk()
petWalker = &filepath.FilePath{}
petWalker.Walk()

println("\ncall by filepath.Walker:")
filepathWalker = &pet.Dog{}
filepathWalker.Walk()
filepathWalker = &pet.Cat{}
filepathWalker.Walk()
filepathWalker = &filepath.FilePath{}
filepathWalker.Walk()

println("\nThe strange is that pet.Warker and filepath.Walker has the same signiture but they are not the same one.")
println("But Go treat them as the same one.")


从语法上修复这个bug的方法如下:

implements pet.Walker{
    *pet.Dog
    *pet.Cat
}

implements *filepath.FilePath{
    filepath.Walker
    filepath.Reader
}

通过显式的申明 实现并可以使用接口的具体类型,告诉编译器什么样的接口赋值,是被允许的。

这种外部申明的语法,仍然没有破坏GO interface非侵入式的设计,无须对interface和实现类型做任何修改。

这样,下面的接口赋值将被编译器判断为非法

filepathWalker  = &pet.Dog{}

另外,这种显式申明还有一个好处,就是可以明确通过查找引用的方法,找出实现了某个接口的所有实现类型。

起到一个建立接口定义与实现类型关系的书面说明,

不会像现在一样,通过interface名字,只能找到interface的对象,却没法找出所有实现并赋值给该接口的所有具体类型的信息。

参考链接:

Russ Coss: interface https://research.swtch.com/interfaces

Ian Lance Taylor: go interface https://www.airs.com/blog/archives/277

confused interface: https://github.com/vipally/glab/blob/master/lab12/walk_test.go

猜你喜欢

转载自blog.csdn.net/vipally/article/details/81517918