MST

星途 面试题库

面试题:Go语言接口的嵌入与方法集的覆盖及接口值的变化

假设有两个接口 `A` 和 `B`,`B` 嵌入了 `A`。定义结构体 `S` 实现了 `B` 接口的部分方法(未完全实现 `A` 接口的所有方法),定义结构体 `T` 完全实现了 `B` 接口。请分析在将 `S` 和 `T` 的实例赋值给 `A` 接口类型变量、`B` 接口类型变量时,方法集的情况以及接口值的变化,并通过代码示例说明。
15.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

分析

  1. S 实例赋值给 A 接口类型变量
    • S 未完全实现 A 接口所有方法,所以不能赋值给 A 接口类型变量,否则编译报错。
  2. S 实例赋值给 B 接口类型变量
    • S 实现了 B 接口部分方法,所以可以赋值给 B 接口类型变量。此时方法集为 S 所实现的 B 接口的那些方法。
  3. T 实例赋值给 A 接口类型变量
    • T 完全实现了 B 接口,而 B 嵌入了 A,所以 T 也完全实现了 A 接口。可以赋值给 A 接口类型变量,方法集为 A 接口的所有方法。
  4. T 实例赋值给 B 接口类型变量
    • 可以赋值给 B 接口类型变量,方法集为 B 接口的所有方法(包括嵌入的 A 接口的方法)。

代码示例(以 Go 语言为例)

package main

import "fmt"

// A 接口
type A interface {
    MethodA()
}

// B 接口,嵌入 A 接口
type B interface {
    A
    MethodB()
}

// S 结构体,实现 B 接口部分方法
type S struct{}

func (s S) MethodB() {
    fmt.Println("S.MethodB")
}

// T 结构体,完全实现 B 接口
type T struct{}

func (t T) MethodA() {
    fmt.Println("T.MethodA")
}

func (t T) MethodB() {
    fmt.Println("T.MethodB")
}

func main() {
    // 尝试将 S 实例赋值给 A 接口类型变量,编译报错
    // var a1 A = S{}

    // 将 S 实例赋值给 B 接口类型变量
    var b1 B = S{}
    b1.MethodB()

    // 将 T 实例赋值给 A 接口类型变量
    var a2 A = T{}
    a2.MethodA()

    // 将 T 实例赋值给 B 接口类型变量
    var b2 B = T{}
    b2.MethodA()
    b2.MethodB()
}

上述代码中:

  • 注释掉的 var a1 A = S{} 会导致编译错误,因为 S 未完全实现 A 接口。
  • b1B 接口类型,指向 S 实例,只能调用 S 实现的 MethodB 方法。
  • a2A 接口类型,指向 T 实例,可以调用 T 实现的 MethodA 方法。
  • b2B 接口类型,指向 T 实例,可以调用 T 实现的 MethodAMethodB 方法。