英文:
How to embed third party types in Go?
问题
在我的应用程序中,使用了 Decimal 包 github.com/shopspring/decimal。
为了在 decimal.Decimal
类型上编写自定义函数,我创建了自己的 Decimal
类型并嵌入了 decimal.Decimal
:
type Decimal struct {
decimal.Decimal
}
这很好用,现在我可以在 Decimal
对象上访问 decimal.Decimal
的方法:
a := Decimal{decimal.NewFromFloat(1.0)}
b := Decimal{a.Neg()}
一些 decimal.Decimal
的方法需要一个 decimal.Decimal
类型的参数,例如:
c := Decimal{a.Add(b)}
上面的代码无法编译,因为出现了错误:cannot use b (variable of type Decimal) as decimal.Decimal value in argument to a.Add
。
我尝试将 Decimal
转换为 decimal.Decimal
:
c := Decimal{a.Add((decimal.Decimal)(b))}
上面的代码无法编译,因为出现了以下错误:
cannot convert b (variable of type Decimal) to decimal.Decimal
**问题:**如何以一种方式扩展/嵌入第三方类型,使得可以使用“父类”方法,并且可以将扩展类型用作需要父类类型参数的方法的参数?
英文:
In my application, the Decimal package github.com/shopspring/decimal is used.
In order to write custom functions on the decimal.Decimal
type, I have created my own Decimal
type and embedded decimal.Decimal
:
type Decimal struct {
decimal.Decimal
}
This works great, and I can now access decimal.Decimal
methods on Decimal
object:
a := Decimal{decimal.NewFromFloat(1.0)}
b := Decimal{a.Neg()}
Some of decimal.Decimal
methods requires an argument of type decimal.Decimal
, f.ex:
c := Decimal{a.Add(b)}
The above line cannot compile because of error: cannot use b (variable of type Decimal) as decimal.Decimal value in argument to a.Add
I have tried to convert Decimal
to decimal.Decimal
:
c := Decimal{a.Add((decimal.Decimal)(b))}
The above code would not compile due to below error:
cannot convert b (variable of type Decimal) to decimal.Decimal
Question: How to extend/embed a third party type in a way that allows the use of "parent" methods and can use the extended type as argument in methods that requires argument of parents type?
答案1
得分: 2
一个声明了类型但没有显式字段名的字段被称为嵌入字段。嵌入字段必须指定为类型名T或指向非接口类型名*T的指针,并且T本身不能是指针类型。未限定的类型名充当字段名。
因此,一个快速而简单的解决方案是使用"未限定的类型名"来访问该字段。
_ = Decimal{a.Add(b.Decimal)}
然而,如果你希望在使用新类型时获得更无缝的体验,那么你唯一的选择就是重新声明需要原始类型的方法,并在其中使用新类型。这些重新声明的方法只需要是简单的包装器,将一个实例的嵌入字段传递给另一个实例的嵌入字段的方法。例如:
type Time struct {
time.Time
}
func (t Time) In(loc *time.Location) Time {
return Time{t.Time.In(loc)}
}
func (t Time) Equal(u Time) bool {
return t.Time.Equal(u.Time)
}
英文:
> A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.
So a quick and dirty solution would be to simply access the field using the "unqualified type name".
_ = Decimal{a.Add(b.Decimal)}
If, however, you're looking for a more seamless experience when using the new type, then your only option is to redeclare the methods that require the original type and use the new type in its place. These redeclared methods need only be simple wrappers that pass the embedded field of one instance to the method of the embedded field of the other instance. For example:
type Time struct {
time.Time
}
func (t Time) In(loc *time.Location) Time {
return Time{t.Time.In(loc)}
}
func (t Time) Equal(u Time) bool {
return t.Time.Equal(u.Time)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论