[英]Problem with implementing a trait over another trait with associated types in Rust
我有這個特點:
trait Pokemon {
type Move;
fn pick_move(&self) -> Self::Move;
}
某些類型實現了 trait,如下所示:
#[derive(PartialEq, Clone, Copy)]
enum Fire {
Charmander,
Charmeleon,
Charizard
}
#[derive(PartialEq, Clone, Copy)]
enum FireMove {
Ember, FlameThrower, FireBlast
}
#[derive(PartialEq, Clone, Copy)]
enum Water {
Squirtle,
Wartortle,
Blastoise
}
#[derive(PartialEq, Clone, Copy)]
enum WaterMove {
Bubble,
WaterGun
}
impl Pokemon for Fire {
type Move = FireMove;
fn pick_move(&self) -> Self::Move {
match self {
Self::Charmander => Self::Move::Ember,
Self::Charmeleon => Self::Move::FlameThrower,
Self::Charizard => Self::Move::FireBlast,
}
}
}
impl Pokemon for Water {
type Move = WaterMove;
fn pick_move(&self) -> Self::Move {
if *self == Water::Squirtle {
return Self::Move::Bubble;
}
Self::Move::WaterGun
}
}
對於實現Pokemon
trait 的類型,我想實現一個 trait Battle
:
trait Battle {
fn battle(&self) -> ??;
}
最后,我想要實現的是我應該能夠在任何實現Pokemon
特性的類型上調用.battle
並最終能夠返回贏得戰斗的 Pokemon。
我也考慮過使用這樣的方法:
fn battle<T>(pokemon: T, foe: T) -> T
where T: Pokemon
{
let p_move = pokemon.pick_move();
let f_move = foe.pick_move();
if p_move == f_move {
return pokemon;
}
foe
}
不幸的是,在這里我無法比較已傳遞參數的Move
。
我接近實現這一目標的一種方法是做這樣的事情:
trait Battle {
type Pokemons;
fn battle(&self, foe: Self::Pokemons) -> Self::Pokemons;
}
#[derive(PartialEq, Clone, Copy)]
enum PokemonTypes {
Fire(Fire),
Water(Water),
Grass(Grass)
}
impl Battle for Fire {
type Pokemons = PokemonTypes;
fn battle(&self, foe: Self::Pokemons) -> Self::Pokemons {
match foe {
Self::Pokemons::Water(pokemon) => Self::Pokemons::Water(pokemon),
_ => Self::Pokemons::Fire(*self) // because Fire beats Grass type
}
}
}
所以基本上,我如何實現這個Battle
特性來幫助我比較動作和/或口袋妖怪類型並決定獲勝者?
您可以將移動類型抽象為另一個枚舉,並刪除特征中的關聯類型:
#[derive(PartialEq, Clone, Copy)]
enum Move {
Water(WaterMove),
Fire(FireMove),
}
trait Pokemon {
fn pick_move(&self) -> Move;
}
然后以同樣的方式,您可以直接使用Battle
系統的實現,但通過PokemonType
實現對戰:
#[derive(PartialEq, Clone, Copy)]
enum PokemonType {
Fire(Fire),
Water(Water),
}
trait Battle {
fn battle(&self, foe: PokemonType) -> PokemonType;
}
impl Battle for PokemonType {
fn battle(&self, foe: PokemonType) -> PokemonType {
match (self, foe) {
(p1@PokemonType::Water(_), p2@PokemonType::Fire(_)) => {
*p1
// do watever
}
_ => foe // handle other patterns
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.