go语言·
1,方法
2,接口
//方法 其实方法就是一个函数 /* 基础知识: 1.方法:对象绑定方法,类绑定方法 特点:就是可以自动传值 2,在Python中,写在类当中,没有加装饰器的,从严格意义说,如果类来调,就是一个函数,对象调,就是方法 类来调,有几个参数就传几个参数,self要自己手动传 go方法: //语法 (a Person)叫接受器称之为方法 //func (a Person) getName() { //} //方法是给对象用的,给结构体绑定方法 //例如给Person结构体加一个打印名字的方法
type Person struct { name string age int } //语法 (a Person)叫接受器称之为方法 //func (a Person) getName() { //} //方法是给对象用的,给结构体绑定方法 //例如给Person结构体加一个打印名字的方法 func (a Person) printName() { // printName()就是普通函数,有返回值就在后面加返回值类型 fmt.Println(a.name) } //普通函数 func printName(a Person) { fmt.Println(a.name) } func (a *Person) changeName(name string){ a.name=name fmt.Println(a) } func main() { //p:=Person{name:"lqz"} //p.printName() ////执行函数 //printName(p) //为什么已经有函数了,还要有方法? // 方法有了,就相当于你拿到一个百宝箱,直接可以点拿到结构体中属性,面向对象的 // 而函数需要一个个去传去取 p:=&Person{name:"lqz"} p.changeName( "qqq") fmt.Println(p) //值接受器与指针类型接受器 //值接受器相当于新copy一份过去,进行改的时候改的是copy过来的,不影响原来的 //指针接受器是地址 //func (a Person) printName() 即func (写值) printName(),在内部修改值,不会影响外部的值 //func (a *Person) printName() 即func (指针) printName(name string) 在内部修改值,会影响外部的值 //什么时候用指针接受器,什么时候用值接受器 // 是否改变外部值和拷贝结构体的代价 }
package main import "fmt" //匿名字段的方法 可以提升 type Person1 struct { name string age int sex int Hobby //匿名字段 不匿名不会提升 } type Hobby struct { id int hobbyname string } func (h Hobby) printHobbyId() { //绑定方法 fmt.Println(h.id) } func (a Person1) printName() { fmt.Println(a.name) } func (a *Person1) changeName(name string) { a.name=name fmt.Println(a) } func main() { p:=Person1{name:"lqz",Hobby:Hobby{id:10}} //p.printHobbyId() //正常操作 p.Hobby.printHobbyId() //10 //非正常操作,方法也提升了 p.printHobbyId() //10 用了面向对象继承的方法,自己有调自己,自己没有调父类的思想 }
package main import "fmt" // 在方法中使用值接受器 与 在函数中使用值接受器 // 在方法中使用指针接受器 与 在 函数中只要指针接受器 type Person2 struct { name string age int sex int } //函数中使用值作为参数 func printName1(a Person2) { fmt.Println(a.name) } //函数中使用指针作为参数 func printName2(a *Person2) { //fmt.Println((*a).name) //支持下面的写法 fmt.Println(a.name) } //在方法中使用值接受器 func (a Person2)printName() { fmt.Println(a.name) } // 在方法中使用指针接受器 func (a *Person2)printName2() { fmt.Println(a.name) } func main() { p:=Person2{name:"kkk"} // 调用值接受器 p.printName() // 调用指针接受器 p.printName2() //调用值函数 printName1(p) //调用指针函数 printName2(&p) //总结:不管是值接受器还是指针接受器,都可以使用值来调用 // 不管是值接收器还是指针接受器,都可以使用指针来调用 // 在函数中,是什么参数,就得传什么参数 pp:=&Person2{name:"kkkk"} pp.printName() pp.printName2() }
非结构体上绑定方法 package main import "fmt" //非结构体上的方法, (接收器可以是结构体,也可以是非结构体) //func (i int)add() { // i++ //} //重命名 ,传统的不支持绑定方法,你可以重命名后绑定方法 type Myint int //func (i Myint) add() { // i++ // fmt.Println(i) //11 ,但是fmt.Println(a)为10 // //} func (i *Myint) add() { (*i)++ fmt.Println(i) //打印的是地址 fmt.Println(*i) // 11 } func main() { var a Myint=10 a.add() fmt.Println(a) //11 }
接口
package main import "fmt" //接口 /* 接口是一系列方法的集合 语法: type 接口名 interface { 方法一 方法二 } */ //定义了一个鸭子接口 type Duck interface{ run() //func 关键字省略, 此时该方法没有返回值,可以不写 speak() //runn()() 后面第一括号里为参数,第二个括号里为返回值 例如 run(a int)int } //实现该接口(结构体要实现接口,只要该结构体实现了接口中的所有的方法,就实现了该接口) //侵入式接口和非侵入式接口 // java当中必须要实现的接口就是侵入式接口,必须要实现的,只要把那个接口拿掉就会报错,java,c++ // 在python和go中都是非侵入式接口,可以把接口拿掉,不会影响程序的运行,不会报错,,不会对你代码造成影响 //定义一个普通鸭子的结构体 type PDuck struct { name string age string } //实现run方法 func (p PDuck)run() { fmt.Println("我是普通鸭子,名字叫",p.name,"走路爽歪歪") } //实现speak func (p PDuck)speak() { fmt.Println("我是普通鸭子,名字叫",p.name,"各个说过话") } //定义一个唐老鸭的结构体 type TDuck struct { name string age string wife bool } //实现run方法 func (p TDuck)run() { fmt.Println("我是唐老鸭,名字叫",p.name,"走路爽歪歪") } //实现speak func (p TDuck)speak() { fmt.Println("我是唐老鸭,名字叫",p.name,"各个说过话") } func main() { pD:=PDuck{name:"水鸭子"} tD:=TDuck{name:"唐老鸭"} //写一个函数让鸭子说话,不管是水鸭子,还是唐老鸭 speak(pD) speak(tD) //定义一个鸭子类型的变量 var d Duck //给类型定义变量 d = pD d = tD fmt.Println(d) //类似于面向对象的多态,鸭子有多种形态 // 问题研究,想在函数中拿出唐老鸭的wife属性 speak(tD) } //写一个函数让鸭子说话,不管是水鸭子,还是唐老鸭 // 只能分别写,下面这种写法太麻烦,代码冗余 改进方法用 //func speak(p PDuck) { // p.speak() //} //func speak2(t TDuck) { // t.speak() //} //改进方法 传类型 //func speak(p Duck) { // //p.speak() //只要是同一类事物,都可以传过来 // // 问题研究,想在函数中拿出唐老鸭的wife属性 // //在这里拿属性 // //就用类型断言,断言你是TDuck类型,如果没有问题,转成TDuck类型 // a:=p.(TDuck) // fmt.Println(a.wife) // p.speak() //} // func speak(p Duck) { switch a:=p.(type) { //类型不确定,通过case来进行判断 case PDuck: fmt.Println("你是普通鸭子") // 判断是普通鸭子,把普通鸭子的名字拿出来 fmt.Println(a.name) case TDuck: // 判断是唐老鸭,把唐老鸭的wife拿出来 fmt.Println("你是唐老鸭") fmt.Println(a.wife) //在不同的类型中a是不一样的 } }
空接
package main import "fmt" //空接口(里面一个方法都没有) // 是不是所有的类型都实现了空接口,是 //所有的类型都可以赋值给空接口 type Empty interface { } type speaks struct { name string } func main() { test(1) test("sss") p:=speaks{name:"kkk"} test(p) //什么类型都支持 test4(1) test4("sss") p1:=speaks{name:"kkkee"} test4(p1) } func test(a Empty) { fmt.Println(a) } func test4(a interface{}) { switch a.(type) { case int: fmt.Println("我是int类型") case string: fmt.Println("我是字符串类型") default: fmt.Println("不知道是什么类型") } }
实现多个接口
接口嵌套
接口的零值是nil类型,即接口是引用类型