I am looking to be able to compare a Card with another Card of the same type. For example an instance of a HarryPotterCard should be able to call its .cmp() method against another instance of a HarryPotterCard.
The issue that I am facing is if I put a HarryPotterCard in the implementation of the cmp function signature for HarryPotterCard it complains that the signatures dont match and if I put a regular Card type then I cannot access the magic and cunning attributes to compare against self
Any help or suggestions is appreciated.
pub struct HarryPotterCard {
name: String,
magic: u32,
cunning: u32,
}
pub struct DinosaurCard {
name: String,
height: f32,
weight: f32,
}
pub trait Card {
fn cmp(&self, other:Box<dyn Card>, field: &str) -> bool;
}
impl Card for DinosaurCard { {
pub fn cmp(&self, other: Box<dyn DinosaurCard>, field: &str) -> bool {
match field {
"height" => self.height > other.height,
"weight" => self.weight > other.weight,
}
}
}
impl Card for HarryPotterCard {
pub fn cmp(&self, other: Box<dyn HarryPotterCard>, field: &str) -> bool {
match field {
"magic" => self.magic > other.magic,
"cunning" => self.cunning > other.cunning,
}
}
}
>Solution :
Since you only want cards to be compared against another of the same type, you probably don’t want to use dyn, since that would allow any type of cards to be compared, which is definitely not fair to the poor dinosaurs who have to fight a wizard. You can use Self in the trait declaration, which will limit the other to be the same type as self. To actually implement the trait though, you need to specify it explicitly in your impl block, otherwise it’s just a normal method.
pub struct HarryPotterCard {
name: String,
magic: u32,
cunning: u32,
}
pub struct DinosaurCard {
name: String,
height: f32,
weight: f32,
}
pub trait Card {
fn cmp(&self, other:Box<Self>, field: &str) -> bool;
}
impl Card for DinosaurCard {
fn cmp(&self, other: Box<DinosaurCard>, field: &str) -> bool {
match field {
"height" => self.height > other.height,
"weight" => self.weight > other.weight,
_ => panic!("not a real field"),
}
}
}
impl Card for HarryPotterCard {
fn cmp(&self, other: Box<HarryPotterCard>, field: &str) -> bool {
match field {
"magic" => self.magic > other.magic,
"cunning" => self.cunning > other.cunning,
_ => panic!("not a real field"),
}
}
}
Because you aren’t able to use trait objects in this scenario (dyn), I would also suggest switching out Box<WhateverCard> with &WhateverCard so that it is a little friendlier to use, as you don’t need to heap allocate your data when you call cmp.