使用 Go 1.18 泛型,如何使用约束类型作为需要具体类型的函数的参数?
With Go 1.18 generics, how to use constrained type as argument to function that expects a concrete type?
转到版本:1.18
这是一个不是特别有用的愚蠢示例。我将其用作学习泛型的练习。
我有一个Pokemon
界面
type Pokemon interface {
ReceiveDamage(float64)
InflictDamage(Pokemon)
}
和 Charmander
具有实现 Pokemon
接口的类型参数。
type Float interface {
float32 | float64
}
type Charmander[F Float] struct {
Health F
AttackPower F
}
我想用Charmander
的攻击力造成伤害
func (c *Charmander[float64]) ReceiveDamage(damage float64) {
c.Health -= damage
}
func (c *Charmander[float64]) InflictDamage(other Pokemon) {
other.ReceiveDamage(c.AttackPower)
}
我的编译器报错
cannot use c.AttackPower (variable of type float64 constrained by Float) as float64 value in argument to other.ReceiveDamage compiler(IncompatibleAssign)
我已经将泛型结构实例化为 *Charmander[float64]
。我希望编译器知道 AttackPower
是 float64
.
当我将 float64
传递给需要 float64
的函数时,它为什么会抱怨?另一方面,ReceiveDamage
并没有抱怨。我从 Health
中减去 float64
,这是一个受约束的类型。
你必须使用类型转换。方法 ReceiveDamage
需要一个 float64
但主要类型在 F
中被参数化。 F
类型的东西,即使仅限于浮点数,或者即使仅限于一个特定的浮点数, 也不是 float64
。即F
。 (此外,它也可以用 float32
实例化)。
两种转换都可以编译,因为 float64
可以转换为类型参数类型集中的所有类型,float32
和 float64
,以及 vice-versa.
所以方法变成:
func (c *Charmander[T]) ReceiveDamage(damage float64) {
c.Health -= T(damage)
}
func (c *Charmander[T]) InflictDamage(other Pokemon) {
other.ReceiveDamage(float64(c.AttackPower))
}
固定游乐场:https://go.dev/play/p/FSsdlL8tBLn
当 T
实例化为 float32
时,请注意转换 T(damage)
可能会导致精度损失。 (在这个特定用例中这可能不是问题...)
转到版本:1.18
这是一个不是特别有用的愚蠢示例。我将其用作学习泛型的练习。
我有一个Pokemon
界面
type Pokemon interface {
ReceiveDamage(float64)
InflictDamage(Pokemon)
}
和 Charmander
具有实现 Pokemon
接口的类型参数。
type Float interface {
float32 | float64
}
type Charmander[F Float] struct {
Health F
AttackPower F
}
我想用Charmander
的攻击力造成伤害
func (c *Charmander[float64]) ReceiveDamage(damage float64) {
c.Health -= damage
}
func (c *Charmander[float64]) InflictDamage(other Pokemon) {
other.ReceiveDamage(c.AttackPower)
}
我的编译器报错
cannot use c.AttackPower (variable of type float64 constrained by Float) as float64 value in argument to other.ReceiveDamage compiler(IncompatibleAssign)
我已经将泛型结构实例化为 *Charmander[float64]
。我希望编译器知道 AttackPower
是 float64
.
当我将 float64
传递给需要 float64
的函数时,它为什么会抱怨?另一方面,ReceiveDamage
并没有抱怨。我从 Health
中减去 float64
,这是一个受约束的类型。
你必须使用类型转换。方法 ReceiveDamage
需要一个 float64
但主要类型在 F
中被参数化。 F
类型的东西,即使仅限于浮点数,或者即使仅限于一个特定的浮点数, 也不是 float64
。即F
。 (此外,它也可以用 float32
实例化)。
两种转换都可以编译,因为 float64
可以转换为类型参数类型集中的所有类型,float32
和 float64
,以及 vice-versa.
所以方法变成:
func (c *Charmander[T]) ReceiveDamage(damage float64) {
c.Health -= T(damage)
}
func (c *Charmander[T]) InflictDamage(other Pokemon) {
other.ReceiveDamage(float64(c.AttackPower))
}
固定游乐场:https://go.dev/play/p/FSsdlL8tBLn
当 T
实例化为 float32
时,请注意转换 T(damage)
可能会导致精度损失。 (在这个特定用例中这可能不是问题...)