软件包term:

type Num interface {
    IsNeg()  bool
    Add(Num) Num
}

type Term struct {
    Coeff Num
    Var   string
}

外部包装frac64
type Frac64 struct {
    Numer uint64
    Denom uint64
    Neg   bool
}

func (a Frac64) Add(b Frac64) Frac64 { // Pretend this is implemented }

软件包client
type Frac Frac64

func (f Frac) IsNeg()  bool   { return f.Neg }
func (f Frac) Add(v Num) Num  { // Call Frac64's Add here? }

我将如何实现AddFrac,以便它实现Num接口(interface)?

编辑:附加信息

外部软件包frac64只是一个示例。我不打算使用它。

这里的目标(我应该更清楚)是我的包公开使用Term作为其两个属性之一的struct Num。现在,我希望我的软件包的用户能够使用big.RatFrac64int64rune或他们想要的任何东西,只要他们实现Num接口(interface)即可。

我遇到的问题是尝试为已经具有与Num中的函数同名的函数的结构实现Num接口(interface)。这就是Frac64出现的地方。我还可以使用big.Rat为例,因为它也有一个名为Add的函数。

我不能更改Frac64(或big.Rat)的实现,也不能使用Add函数扩展它,因为它已经存在。这就是为什么我尝试使用type Frac Frac64(或type Frac big.Rat),然后尝试扩展Frac的原因。

但是我无法为Num实现Frac,因为我无法从Frac64Add函数调用FracAdd

最佳答案

您可以使用embedding解决此问题...

type Frac struct {
    *Frac64
}

现在Frac可以使用Frac64的方法,而无需重写它们。
// `Frac.New(numer, denom, bool)` would remove this implementation leak.
foo := Frac{
    &Frac64 {
        Numer: 45,
        Denom: 99,
        Neg: false,
    },
}
fmt.Println(foo.IsNeg())

但是,当我们尝试使用Add时有一个障碍。
// cannot use foo (type Frac) as type Frac64 in argument to foo.Frac64.Add
fmt.Println(foo.Add(foo))

嵌入仅适用于继承方法。当用作参数时,它不会为您使用嵌入式引用,您必须显式地执行此操作。

真正的问题是func (a Frac64) Add(b Frac64) Frac64不满足Num接口(interface)。如果我们修复它工作正常,因为Frac实现Num
func (a Frac64) Add(b Num) Num {
    return Frac64{
        Numer: 12,
        Denom: 23,
        Neg: false,
    }
}

可以,但是从更特定的类型Frac来构建一个较不特定的类型Frac64是很尴尬的。

从这里开始,Frac是带有某些扩展名的Num变得更加明显。 Frac应该是扩展Num并添加分子和分母的接口(interface)。 Frac64成为实现Frac的类型。
type Num interface {
    IsNeg()  bool
    Add(Num) Num
}

type Frac interface {
    Numer() uint
    Denom() uint
    Num
}

type Frac64 struct {
    numer uint64
    denom uint64
    neg bool
}

func (f Frac64) IsNeg() bool {
    return f.neg
}

func (f Frac64) Numer() uint {
    return uint(f.numer)
}

func (f Frac64) Denom() uint {
    return uint(f.denom)
}

func (a Frac64) Add(b Num) Num {
    // Just a placeholder to show it compiles.
    return Frac64{
        numer: 12,
        denom: 34,
        neg: false,
    }
}

这对练习很好。在生产中,请考虑使用 big.Rat

关于go - 与返回自身的方法接口(interface),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49119362/

10-13 03:37