包裹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? }
我如何为Add
实施Frac
,以便它实现Num
界面?
外部包frac64
只是一个例子。我不打算用它。
这里的目标(我应该更清楚)是我的包公开了使用Term
作为其两个属性之一的结构Num
。现在,我希望我的包的用户能够使用big.Rat
或Frac64
或int64
或rune
或他们想要的任何内容,只要他们实现{{1接口。
我遇到的问题是尝试为已经具有与Num
中的函数同名的函数的结构实现Num
接口。这是Num
的用武之地。我也可以使用Frac64
作为示例,因为它还有一个名为big.Rat
的函数。
我无法更改Add
(或Frac64
的实现),而且我也无法使用big.Rat
函数扩展它,因为它已经存在。这就是为什么我尝试使用Add
(或type Frac Frac64
)然后尝试扩展type Frac big.Rat
。
我无法为Frac
实施Num
,因为我无法从Frac
的{{1}} Frac64
Add
{ {1}}功能。
答案 0 :(得分:2)
您可以使用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接口。如果我们修复它可以正常工作,因为Frac
实现了Num
。
func (a Frac64) Add(b Num) Num {
return Frac64{
Numer: 12,
Denom: 23,
Neg: false,
}
}
这很有效,但是从更具体的类型Frac
构建一个不太具体的类型Frac64
很尴尬。
从这里开始,Frac
是一个带有一些扩展名的Num
变得更加明显。 Frac
应该是一个扩展Num
并添加分子和分母的接口。 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
。
答案 1 :(得分:0)
您实现它以使其具有与接口相同的签名;因此必须将其命名为Add
,它必须采用类型Num
的单个参数,并且必须返回类型为Num
的单个值。请注意,这并不意味着它可以获取或返回实现Num
的类型的值 - 签名必须相同:
func (a Frac64) Add(b Num) Num {
// Pretend this is implemented
// It can return anything that implements Num
}