Reputation: 725
Go version: 1.18
Here's a silly example that is not particularly useful. I am using this as an exercise to learn generics.
I have a Pokemon
interface
type Pokemon interface {
ReceiveDamage(float64)
InflictDamage(Pokemon)
}
and Charmander
with type parameter that implements the Pokemon
interface.
type Float interface {
float32 | float64
}
type Charmander[F Float] struct {
Health F
AttackPower F
}
I want to use Charmander
's attack power to inflict damage.
func (c *Charmander[float64]) ReceiveDamage(damage float64) {
c.Health -= damage
}
func (c *Charmander[float64]) InflictDamage(other Pokemon) {
other.ReceiveDamage(c.AttackPower)
}
My compiler gives error
cannot use c.AttackPower (variable of type float64 constrained by Float) as float64 value in argument to other.ReceiveDamage compiler(IncompatibleAssign)
I already instantiated the struct generic as *Charmander[float64]
. I'd expect that the compiler knows AttackPower
is a float64
.
When I pass a float64
into a function that expects float64
, why should it complain? On the other hand, ReceiveDamage
does not complain. I am subtracting a float64
from Health
which is a constrained type.
Upvotes: 7
Views: 2956
Reputation: 44698
You have to use type conversions. The method ReceiveDamage
expects a float64
but the main type is parametrized in F
. Something of type F
, even if constrained to floats only, or even if constrained to one specific float, is not float64
. It is F
. (Moreover, it could also be instantiated with float32
).
Both conversions compile because float64
is convertible to all types in the type parameter's type set, float32
and float64
, and vice-versa.
So the methods become:
func (c *Charmander[T]) ReceiveDamage(damage float64) {
c.Health -= T(damage)
}
func (c *Charmander[T]) InflictDamage(other Pokemon) {
other.ReceiveDamage(float64(c.AttackPower))
}
Fixed playground: https://go.dev/play/p/FSsdlL8tBLn
Watch out that the conversion T(damage)
may cause loss of precision when T
is instantiated with float32
. (Probably this won't be an issue in this specific use case...)
Upvotes: 4