MST

星途 面试题库

面试题:Go接口封装中的组合与继承权衡

Go语言通过组合来实现类似继承的功能,在接口封装方面,如何基于组合的方式设计一组接口,既能复用已有接口的功能,又能满足新的业务需求?请结合具体代码示例说明,并分析这种设计相较于传统继承方式在接口封装上的优势与劣势。
27.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

基于组合方式设计接口示例

假设我们有一个基础的 Writer 接口,定义如下:

type Writer interface {
    Write(p []byte) (n int, err error)
}

现在我们有一个新的业务需求,需要一个 BufferedWriter,它不仅能写数据,还能在内部维护一个缓冲区。我们可以通过组合 Writer 接口来实现:

type BufferedWriter struct {
    Writer
    buffer []byte
}

func (bw *BufferedWriter) Write(p []byte) (n int, err error) {
    // 先将数据写入缓冲区
    bw.buffer = append(bw.buffer, p...)
    // 这里可以添加逻辑,当缓冲区满了再调用底层的 Writer 写入数据
    return len(p), nil
}

优势

  1. 灵活性更高:传统继承方式下,子类紧密依赖父类,耦合度高。而组合方式允许在运行时动态替换组合的接口实现,例如 BufferedWriter 可以组合不同类型的 Writer 实现,如 os.Stdout 实现的 Writer 接口或者网络连接实现的 Writer 接口等。
  2. 避免多重继承问题:在传统继承中,多重继承会带来诸如菱形继承等复杂问题。而Go语言通过组合方式,不存在多重继承的困扰,代码结构更加清晰。
  3. 接口复用粒度更细:组合可以选择复用部分接口功能,而不是像继承那样继承整个类及其所有功能,例如 BufferedWriter 只复用了 Writer 接口的 Write 方法,对于其他可能存在于 Writer 实现类中的非接口方法,BufferedWriter 无需关心。

劣势

  1. 代码量可能增加:与继承相比,通过组合实现功能可能需要更多的样板代码。例如在上述 BufferedWriter 中,需要手动实现 Write 方法来调用组合的 Writer 接口的 Write 方法,如果有多个方法需要转发,代码量会有所增加。
  2. 关系不够直观:继承方式能很直观地看出类之间的层次关系,而组合方式对于类之间的关系理解相对需要更多的代码阅读,尤其是对于复杂的组合结构,理解成本稍高。