Go面试:Go通过匿名组合实现的继承和Java的继承之间的差别

 Go没有直接的继承关键字,只能用结构体的匿名组合来实现继承,在实现机制和效果上和Java的继承是有差异的,虽然两者都是在编译期实现的。
示例Go代码:

type People struct {
}

func (p *People) ShowA() {
        fmt.Println("showA")
        p.ShowB()
}
func (p *People) ShowB() {
        fmt.Println("showB")
}

type Teacher struct {
        People
}

func (t *Teacher) ShowB() {
        fmt.Println("teachershowB")
}
func main() {
        t := Teacher{}
        t.ShowA()
}

输出:
showA
showB


如果改成对应的Java代码:

public class People {
	public void showA() {
		System.out.println("ShowA");
		this.showB();
	}
	public void showB() {
		System.out.println("ShowB");
	}
}
public class Teacher extends People{
	
	public void showB() {
		System.out.println("ShowTeacherB");
	}
	
	public static void main(String[] args){
		Teacher t = new Teacher();
		t.showA();
	}
}

则输出:
ShowA
ShowTeacherB

为什么会有这种差异呢?因为在编译期,Go的编译器会自动给Teacher生成一个ShowA函数,内部调用一个People实例的showA函数,这样调用顺序是Teacher.ShowA()->People.ShowA()->People.ShowB()。Go的继承在运行时仍然是一个组合关系,Teacher仍然要通过People的实例去调用People的函数。

func (t *Teacher) ShowA() {
         t.People.ShowA()
}

Java的编译器则会把People ShowA函数的内容拷贝过来给Teacher生成一个ShowA函数,里面的this在运行时对应的就是Teacher的实例,所以调用顺序是Teacher.showA()->Teacher.showB()。Java在运行时Teacher实例内部不会再有People的实例存在。

public void showA() {
	System.out.println("ShowA");
	this.showB();
}

附:
Go关于新生成的Teacher.ShowA函数的汇编代码如下。其中调用People.ShowA函数的代码是

“ 0x001c 00028 (<autogenerated>:1)        JMP     "".(*People).ShowA(SB)”

"".(*Teacher).ShowA STEXT dupok size=40 args=0x4 locals=0x0
        0x0000 00000 (<autogenerated>:1)        TEXT    "".(*Teacher).ShowA(SB), DUPOK|ABIInternal, $0-4
        0x0000 00000 (<autogenerated>:1)        MOVL    TLS, CX
        0x0007 00007 (<autogenerated>:1)        MOVL    (CX)(TLS*2), CX
        0x000d 00013 (<autogenerated>:1)        CMPL    SP, 8(CX)
        0x0010 00016 (<autogenerated>:1)        JLS     33
        0x0012 00018 (<autogenerated>:1)        FUNCDATA        $0, gclocals·1a65e721a2ccc325b382662e7ffee780(SB)
        0x0012 00018 (<autogenerated>:1)        FUNCDATA        $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
        0x0012 00018 (<autogenerated>:1)        FUNCDATA        $2, gclocals·9fb7f0986f647f17cb53dda1484e0f7a(SB)
        0x0012 00018 (<autogenerated>:1)        PCDATA  $0, $1
        0x0012 00018 (<autogenerated>:1)        PCDATA  $1, $1
        0x0012 00018 (<autogenerated>:1)        MOVL    ""..this+4(SP), AX
        0x0016 00022 (<autogenerated>:1)        TESTB   AX, (AX)
        0x0018 00024 (<autogenerated>:1)        PCDATA  $0, $0
        0x0018 00024 (<autogenerated>:1)        PCDATA  $1, $0
        0x0018 00024 (<autogenerated>:1)        MOVL    AX, ""..this+4(SP)
        0x001c 00028 (<autogenerated>:1)        JMP     "".(*People).ShowA(SB)
        0x0021 00033 (<autogenerated>:1)        NOP
        0x0021 00033 (<autogenerated>:1)        PCDATA  $1, $-1
        0x0021 00033 (<autogenerated>:1)        PCDATA  $0, $-1
        0x0021 00033 (<autogenerated>:1)        CALL    runtime.morestack_noctxt(SB)
        0x0026 00038 (<autogenerated>:1)        JMP     0

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值