< 返回版块

kaixinbaba 发表于 2021-01-07 16:29

Tags:trait, Hash

大致伪代码如下:

use std::collections::{HashMap, HashSet};
use std::hash::Hash;

trait MyTrait: Eq + Hash {
    fn method(&self);
}

#[derive(Debug, Eq, PartialEq, Hash)]
struct MyTraitImpl;

impl MyTrait for MyTraitImpl {
    fn method(&self) {
        println!("hello trait");
    }
}

fn func(hss: HashSet<Box<dyn MyTrait>>) {
    let mut hs = HashSet::new();
    hs.union(&hss);
}

fn main() {
    let mut hs = HashSet::new();
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    println!("{:?}", hs);
    func(hs);
}

报错是:

error[E0038]: the trait `MyTrait` cannot be made into an object

4   | trait MyTrait: Eq + Hash {
    |       ------- this trait cannot be made into an object...
...
17  | fn func(hss: HashSet<Box<dyn MyTrait>>) {
    |                          ^^^^^^^^^^^ the trait `MyTrait` cannot be made into an object
    | 
   ::: /Users/junjiexun/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/cmp.rs:264:15
    |
264 | pub trait Eq: PartialEq<Self> {
    |               --------------- ...because it uses `Self` as a type parameter in this

这代码要怎么改才能通过编译呢。。。还是说放进HashSet的只能是结构体吗?求助各位

评论区

写评论
xin-water 2021-01-08 14:44

hs.insert(Box::new(MyTraitImpl) as &mut dyn MyTrait);

将 类引用 转换成 接口引用 就可以了; 用 Box, Arc 也行。

ywxt 2021-01-08 11:39
fn main() {
    let mut hs = HashSet::new();
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    println!("{:?}", hs);
    for h in hs.iter() {
        println!("{:?}", h);
    }
    func(hs);
}
fn func(hss: HashSet<Box<impl MyTrait + Eq + Hash>>) {
    let hs = HashSet::new();
    hs.union(&hss);
}
trait MyTrait {
    fn method(&self);
}
#[derive(Debug, Eq, PartialEq, Hash)]
struct MyTraitImpl;

impl MyTrait for MyTraitImpl {
    fn method(&self) {
        println!("hello");
    }
}

泛型版本

作者 kaixinbaba 2021-01-07 18:53

万分感谢,我看看

--
👇
ywxt: ```rust use std::cmp::Ordering; use std::collections::HashSet; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher};

fn main() { let mut hs: HashSet<Box> = HashSet::new(); hs.insert(Box::new(MyTraitImpl)); hs.insert(Box::new(MyTraitImpl)); hs.insert(Box::new(MyTraitImpl)); hs.insert(Box::new(MyTraitImpl)); println!("{:?}", hs); for h in hs.iter() { println!("{:?}", h); } func(hs); } fn func(hss: HashSet<Box>) { let hs = HashSet::new(); hs.union(&hss); } trait MyTrait { fn method(&self);

fn my_hash(&self) -> i32;

fn my_eq(&self, other: &dyn MyTrait) -> bool;
fn my_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;

}

struct MyTraitImpl;

impl MyTrait for MyTraitImpl { fn method(&self) { println!("hello") }

fn my_hash(&self) -> i32 {
    0
}

fn my_eq(&self, other: &dyn MyTrait) -> bool {
    true
}
fn my_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
    f.write_str("hello")
}

}

impl Debug for dyn MyTrait { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.my_fmt(f) } } impl Hash for dyn MyTrait { fn hash<H: Hasher>(&self, state: &mut H) { state.write_i32(self.my_hash()) } }

impl PartialEq for dyn MyTrait { fn eq(&self, other: &Self) -> bool { self.my_eq(other) } }

impl Eq for dyn MyTrait {}

不知道符不符合你的要求
ywxt 2021-01-07 17:19
use std::cmp::Ordering;
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};

fn main() {
    let mut hs: HashSet<Box<dyn MyTrait>> = HashSet::new();
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    hs.insert(Box::new(MyTraitImpl));
    println!("{:?}", hs);
    for h in hs.iter() {
        println!("{:?}", h);
    }
    func(hs);
}
fn func(hss: HashSet<Box<dyn MyTrait>>) {
    let hs = HashSet::new();
    hs.union(&hss);
}
trait MyTrait {
    fn method(&self);

    fn my_hash(&self) -> i32;

    fn my_eq(&self, other: &dyn MyTrait) -> bool;
    fn my_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result;
}

struct MyTraitImpl;

impl MyTrait for MyTraitImpl {
    fn method(&self) {
        println!("hello")
    }

    fn my_hash(&self) -> i32 {
        0
    }

    fn my_eq(&self, other: &dyn MyTrait) -> bool {
        true
    }
    fn my_fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("hello")
    }
}

impl Debug for dyn MyTrait {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        self.my_fmt(f)
    }
}
impl Hash for dyn MyTrait {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_i32(self.my_hash())
    }
}

impl PartialEq for dyn MyTrait {
    fn eq(&self, other: &Self) -> bool {
        self.my_eq(other)
    }
}

impl Eq for dyn MyTrait {}

不知道符不符合你的要求

作者 kaixinbaba 2021-01-07 16:55

好的。。。。。谢谢

--
👇
ywxt: 好像不行,Eq只实现了和&Self的比较,不同类型之间无法比较。

ywxt 2021-01-07 16:51

好像不行,Eq只实现了和&Self的比较,不同类型之间无法比较。

作者 kaixinbaba 2021-01-07 16:30

主要是func这个函数签名,是不知道在HashSet中具体存放的类型的,所以使用了 trait 对象

1 共 7 条评论, 1 页