何为duck Typing
个人通俗解释:不同于类的界门纲目科属种,这种才是鸭子;而是凡是具有鸭子的功能,那就可以认为其是鸭子。
结合代码层面大概是:并非得继承接口(并非一定是鸭科,河鸭属),而是一个sruct只要实现了里面的方法,就可以用这个接口进行调用(就是鸭子了)
非常简单的代码
func main(){
var bbb BBB
bbb = AAA{123}
// 这里对于cesGGG()无所谓AAA实现其他的,只要实现了需要的接口就可以调用,亦即它就是鸭子
cesGGG(bbb)
}
type AAA struct {
aaa int
}
type BBB interface {
BB()
}
type CCC interface {
CC()
}
func cesGGG(bbb BBB) {
bbb.BB()
fmt.Println("OK bbb")
}
func (a AAA) BB(){
fmt.Printf("AAA's BB")
}
func (a AAA) CC(){
fmt.Printf("AAA's CC")
}
大黄鸭代码示例
用大黄鸭解释就是,有个鸭子接口,里面有鸭子叫的方法
一个鸭子struct实现了它,可以用鸭子接口调用
但是一个狗子也实现了它,也可以用鸭子接口调用,那这个狗,他就是个鸭子
详见下列代码
// 定义一个鸭子接口
type duck interface {
Jiao(s string)
}
// 一个函数,这个函数用来逗鸭子,需要传入一个鸭子
func makeFunOfDuck(d duck){
d.Jiao("嘎嘎嘎")
}
// 真鸭子
type realDuck struct {
name string
}
// 狗鸭子,会学鸭子叫的狗
type dogDuck struct {
name string
}
func (dogDuck dogDuck)Jiao(s string) {
fmt.Println(dogDuck.name,s)
}
func (realDuck realDuck)Jiao(s string) {
fmt.Println(realDuck.name,s)
}
func main() {
var d duck
d = realDuck{"real duck"}
makeFunOfDuck(d)
// 这个狗,可以鸭子叫,他就是个鸭子
d = dogDuck{"dog duck"}
makeFunOfDuck(d)
fmt.Println("ces")
ces()
}
func ces(){
var bbb BBB
bbb = AAA{123}
}
复杂一些的代码示例
这里还涉及到一些接口使用方法
// 接口定义好一系列(共性)方法,
// 结构体只要实现接口里的方法,即实现了这个接口,所有的方法都要实现才可以
type Phone interface {
call(receiver string)
msg(receiver string)
}
type mp4 interface {
playVideo(videoName string)
}
// 多个接口组合,亦可以添加自己的方法
// 可以在使用的时候,自己结合大量功能,灵活性高
type smartPhone interface {
Phone
mp4
videoCall(user string)
}
type Nokia struct {
owner string
}
// 各自实现自己想要用的接口
func (nk Nokia) msg(receiver string) {
fmt.Println(nk.owner,"is sending msg to",receiver)
}
func (nk Nokia)call(receiver string) {
fmt.Println(nk.owner," is calling ",receiver)
}
type apple struct {
owner string
}
// 使用者只需要实现方法就行,其他的都不用过问
// 实现了鸭子的叫,那就是鸭子
func (iphone apple)call(receiver string) {
fmt.Println(iphone.owner," is calling ",receiver)
}
func (iphone apple)msg(receiver string) {
fmt.Println(iphone.owner,"is sending msg to",receiver)
}
// 因为要被smartPhone使用,所以还要实现另外的相关接口
func (iphone apple)playVideo(videoName string) {
fmt.Println(iphone.owner,"'s iphone is playing",videoName)
}
func (iphone apple)videoCall(user string) {
fmt.Println(iphone.owner,"is calling ",user, "with video")
}
// 还可以轻松实现系统的接口
func (nk Nokia) String() string {
return fmt.Sprintf("this is %s 's phone",nk.owner)
}
func (iphone apple) String() string {
return fmt.Sprintf("this is %s 's phone",iphone.owner)
}
func main() {
var phone Phone
phone = Nokia{owner: "Tom"}
var iphone smartPhone
iphone = apple{owner: "Steve"}
//main.Nokia this is Tom 's phone,是因为实现了String()
fmt.Printf("%T %v\n",phone, phone)
fmt.Printf("%T %v\n",iphone, iphone)
connectionWithCall(phone,"Steve")
connectionWithCall(iphone,"Tom")
connectionWithMsg(phone,"Steve")
connectionWithMsg(iphone,"Tom")
connectionWithVideo(iphone,"Tom")
iphone.playVideo("video")
}
func connectionWithCall(p Phone,u string) {
p.call(u)
}
func connectionWithMsg(p Phone,u string) {
p.msg(u)
}
func connectionWithVideo(p smartPhone,u string) {
p.videoCall(u)
}