在支持继承的编程语言里什么时候使用类型嵌入?

42 阅读1分钟

如果你熟悉其他支持继承的语言(Java、Python、C++、C#,等等)。例如,我在我的一些包里有一个简单的TempFile 实现,基本上就是这样。

type TempFile struct {
    *os.File
}

func (f TempFile) Close() error {
    if err := f.try("close", func(f TempFile) error {
        return f.File.Close()
    }); err != nil {
        return err
    }
    return f.try("remove", func(f TempFile) error {
        return os.Remove(f.File.Name())
    })
}

func (f TempFile) try(fn func(TempFile) error) error {
    if err := fn(f); err != nil {
        return fmt.Errorf(
            "error attempting to %s file %v: %w",
            what, f.Name(), err,
        )
    }
    return nil
}

所以从本质上讲,我的TempFile 类型的工作原理与*os.File 相同,只是当Close 被调用时,它会调用 "基 "*os.File'的Close 函数,然后删除该文件。如果*os.File 曾经得到一个新的方法,我的TempFile 将 "继承 "它。

然而,这是我能想到的唯一一个我这样做的情况。通常情况下,我最终忘记了嵌入式函数,而不小心做了这样的事情。

func (f TempFile) Read(p []byte) (n int, err error) {
    // ...
    nn, err := self.Read(p)    // oops, I meant self.File.Read...
    // ...
}

这很明显,但我却不止一次地犯同样的错误。我想我只是不适合继承式的嵌入。:upside_down_face: