【interface】特征 & 注意事项

struct的变量,可以调用reciver为this和*this的方法,都可以。

比如

func (p *Person) method() string {
    return "执行method方法"
}
func main() {
    p1 := Person{"Jack"}
    p1.str()
    p2 := &Person{"Jack"}
    p2.str()
}

当p1为变量时,可以调用指针方法,p2为指针时,同样可以。
然而!

type obj interface {
    method() string
}

type Person struct {
    name string
}

func (p *Person) method() string {
    fmt.Println("执行string方法")
    return "ok"
}

func main() {
    var obj obj
    obj = &Person{"Jack"}
    fmt.Println(obj)

}

当Person实现obj接口时,把Person初始化给接口类型obj时,
若实现方法为指针拷贝方法,则必须给obj赋值&Person,obj必须为指针,否则报错。
若实现方法为副本拷贝方法,则给obj赋值Person,&Person都可以。
这是为什么呢?
个人理解,当结构体method实现接口method时,相当于在方法签名种添加了reciver,而结构体实现接口,必须要保证方法签名一致,也就是说,obj必须和(p *Person) 中的形式相同。

接口特征汇总程序:

//接口
/*
interface:
    特征:
    1、接口的实现
    2、接口的组合、嵌套
    3、空接口任意类型
    4、接口断言
    坑:
    当接口包含指针receiver方法时,必须使用指针赋值给接口。
    无法只用值拷贝给接口。
*/
package main

import (
    "fmt"
    "os"
)
type method interface {
    method(string)
}
type ptmethod interface {
    ptmethod(string)
}

//obj嵌套组合了method接口和ptmethod接口(类比java继承)
type obj interface {
    method
    ptmethod
}

//接口的实现,即一个类型实现了一个接口类型所有的方法,即为实现接口,无需显示声明
type person struct {
    name string
}

func (p person) method(str string) {
    fmt.Println(str)
}
func (p *person) ptmethod(str string)  {
    fmt.Println(str)
}
//自定义控制台格式化输出,形参为变长空接口
func myPrint(a ...interface{}) (n int, err error)  {
    return fmt.Fprintln(os.Stdout, a...)
}

func main() {

    var p1 person = person{"Jack"}
    var p2 *person = &person{"Tom"}

    //自身,可以调用 自身方法 & 指针方法
    p1.method("自身调用自身方法")
    p1.ptmethod("自身调用指针方法") //此处应该是golang底层给默认了*p1

    //指针,可以调用 自身方法 & 指针方法
    p2.method("指针调用自身方法")
    p2.ptmethod("指针调用指针方法")

    var intf1,intf2 obj

    //坑 intf1 = p1    如果直接把p1赋值给接口类型,报错:
    /*
    报错信息:cannot use p1 (type person) as type obj in assignment:
            person does not implement obj (ptmethod method has pointer receiver)
            也就是说person没有实现obj,而是*person实现了obj
    结论:当接口包含指针receiver方法时,必须使用指针赋值给接口
    */
    intf1 = &p1
    intf2 = p2

    fmt.Println(intf1,intf2)
    intf1.method("指针接口调用继承而来的method方法")

    //任意类型
    var v1 interface {} = person{"Ada"}
    myPrint(v1)
    v1 = 1
    myPrint(v1)
    v1 = "hello"
    myPrint(v1)
    v1 = map[string]string{"傻子":"小明"}
    myPrint(v1)

    //断言
    if v, bool := v1.(map[string]string) ;bool{
        myPrint(v)
    }else {
        //type 需要和 switch 配套使用
        switch v1.(type){
        case int:
            fmt.Println("v1 为 int")
        default:
            fmt.Println("v1 是什么?who cares")

        }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,805评论 1 32
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 30,381评论 8 265
  • 卡卡_e747阅读 247评论 0 1
  • 《信步语》 人生不过数十载, 有时风雨有时晴。 遥望他山峰顶人, 几分耕耘几分命。 思前顾后枉今时, 弗如定心弗如...
    涵宇尘阅读 305评论 0 0
  • 能耐得住寂寞的人,肯定是有思想的人 ; 能忍受孤独的人,肯定是有理想的人; 遇事能屈能伸的人,肯定是有胸怀的人; ...
    昙天雨落阅读 93评论 0 0

友情链接更多精彩内容