微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Rust 中通过关联类型实现一个 trait 的问题

如何解决在 Rust 中通过关联类型实现一个 trait 的问题

我有这个特点:


trait Pokemon {
    type Move;
    fn pick_move(&self) -> Self::Move;
}

某些类型实现了 trait,如下所示:


#[derive(PartialEq,Clone,copy)]
enum Fire {
    Charmander,Charmeleon,Charizard
}

#[derive(PartialEq,copy)]
enum FireMove {
    Ember,FlameThrower,FireBlast
}

#[derive(PartialEq,copy)]
enum Water {
    Squirtle,Wartortle,Blastoise
}

#[derive(PartialEq,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

我接近实现这一目标的一种方法是做这样的事情:


trait Battle {
    type Pokemons;
    
    fn battle(&self,foe: Self::Pokemons) -> Self::Pokemons;
}

#[derive(PartialEq,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 特征,以帮助我比较动作和/或口袋妖怪类型并决定获胜者?

解决方法

您可以将移动类型抽象为另一个枚举,并删除特征中的关联类型:

postgres=> explain analyze select count(id) from application;
                                                                            QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate  (cost=1245180.18..1245180.19 rows=1 width=8) (actual time=311470.250..311496.933 rows=1 loops=1)
->  Gather  (cost=1245179.96..1245180.17 rows=2 width=8) (actual time=311470.225..311496.919 rows=3 loops=1)
        Workers Planned: 2
        Workers Launched: 2
        ->  Partial Aggregate  (cost=1244179.96..1244179.97 rows=1 width=8) (actual time=311463.287..311463.289 rows=1 loops=3)
            ->  Parallel Seq Scan on application  (cost=0.00..1234885.77 rows=3717677 width=16) (actual time=79.783..311296.505 rows=1202169 loops=3)
Planning Time: 0.083 ms
Execution Time: 311497.021 ms
(8 rows)

然后以同样的方式,您可以直接将您的实现用于 #[derive(PartialEq,Clone,Copy)] enum Move { Water(WaterMove),Fire(FireMove),} trait Pokemon { fn pick_move(&self) -> Move; } 系统,但是实现对 Battle 的战斗:

PokemonType

Playground

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。