rust - 在 Rust 中实现一个特征而不是具有关联类型的另一个特征的问题
问题描述
我有这个特点:
trait Pokemon {
type Move;
fn pick_move(&self) -> Self::Move;
}
某些类型实现了该特征,如下所示:
#[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) -> ??;
}
最后,我想要实现的是我应该能够调用.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
已通过的参数的 s 。
我接近实现这一目标的一种方法是执行以下操作:
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
}
}
}
推荐阅读
- windows - 在 awk 中转义嵌套的双引号
- gradle - Gradle 多项目不会产生 Lombok 的优点
- java - 模拟不返回任何内容的强制转换对象时出现 ClassCastException
- python - Python Pandas if/else Statement
- java - 从 PKCS8 编码数据创建任何 PrivateKey 实例(RSA 或 DSA 或 EC)
- java - 在 LinearLayout 中的随机位置添加 ImageView
- angularjs - 如何使用 ng-click 切换类
- c++ - 使用带有 boost::optional 的相等运算符
- r - Shiny:如何用标题分隔单选按钮列表
- doxygen - Doxygen:如何修复 TreeView 分隔栏,使其延伸到页面底部