< 返回版块

xiaoxineryi 发表于 2021-03-01 13:27

代码如下:

impl Communicate for MockConnector{
    fn set(&self, key: String, value: String) -> KvsResult<()> {
        println!("正在插入数据,key={},value={}",key,value);
        Ok(())
    }
    fn get(&self, key: String) -> KvsResult<Option<String>> {
        println!("正在获取数据");
        Ok(None)
    }
    fn remove(&self, key: String) -> KvsResult<()> {
        println!("正在移除数据");
        Ok(())
    }
}
impl Connect for MockConnector{
    fn connect<T: Communicate>(addr: SocketAddr) -> KvsResult<T> {
        println!("正在连接:{}",addr);
        Ok(MockConnector::new(addr))
    }
}

我这里MockConnector已经实现了Communicate方法,但是在返回时却异常:

Ok(MockConnector::new(addr)) | ^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter T, found struct MockConnector | = note: expected type parameter T found struct MockConnector

请问要怎么做才能返回对应的MockConnector

评论区

写评论
zhylmzr 2021-03-02 11:13

换一种思路,为什额Rust不运行这样编译通过。

如果可以直接返回实现了 Communicate 的结构体,那么假设有两个结构体 A, B 都实现了 Communicat,A结构体很大有100个成员,B结构体很小只有一个成员,两个结构体在大小上不一致,它们都可以通过connect方法返回。那么在程序调用方,每次调用后的变量所占用空间大小不一样是不是很奇怪?

所以为了解决这种问题,就需要返回指针了,比如Box

Aya0wind 2021-03-01 14:23

更正一下,最后那个trait Connect:Sized应该改成trait Connect:Sized+Communicate,Self不仅要有Sized约束,还要有Communicate约束,忘了加了。

--
👇
Aya0wind: 假设你的两个trait是这样写的

trait Communicate {
    fn set(&self, key: String, value: String) -> KvsResult<()>;
    fn get(&self, key: String) -> KvsResult<Option<String>>;
    fn remove(&self, key: String) -> KvsResult<()>;
}
trait Connect<T: Communicate> {
    fn connect(addr: SocketAddr) -> KvsResult<T>;
}

那么就把类型设置成Self就可以了

impl Connect<Self> for MockConnector {
    fn connect(addr: SocketAddr) -> KvsResult<Self> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

还可以使用关联类型

trait Connect {
    type Connector:Communicate;
    fn connect(addr: SocketAddr) -> KvsResult<Self::Connector>;
}

impl Connect for MockConnector {
    type Connector = Self;
    fn connect(addr: SocketAddr) -> KvsResult<Self::Connector> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

当然如果你的Connect就是给Connector实现的trait,那么直接使用Self就好了,不需要显式的泛型。不过Self要一个Sized约束,且Connect不能用作trait object(你这函数里连self参数都没有,也不需要了)。

trait Connect:Sized {
    fn connect(addr: SocketAddr) -> KvsResult<Self>;
}

impl Connect for MockConnector {
    fn connect(addr: SocketAddr) -> KvsResult<Self> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

nujz 2021-03-01 14:23
trait Foo {}
impl Foo for i8 {}

struct Bar;
impl Foo for Bar {}

struct Baz;
impl Foo for Baz {}

fn fna<T: Foo>(a: T) -> T {
    a
}

fn fnb() -> impl Foo {
    Bar
}

fn fnc() -> Box<dyn Foo> {
    if std::env::var("a").is_ok() {
        Box::new(Bar)
    } else {
        Box::new(Baz)
    }
}

fn main() {
    fna(10);
    fnb();
    fnc();
}
Aya0wind 2021-03-01 14:19

假设你的两个trait是这样写的

trait Communicate {
    fn set(&self, key: String, value: String) -> KvsResult<()>;
    fn get(&self, key: String) -> KvsResult<Option<String>>;
    fn remove(&self, key: String) -> KvsResult<()>;
}
trait Connect<T: Communicate> {
    fn connect(addr: SocketAddr) -> KvsResult<T>;
}

那么就把类型设置成Self就可以了

impl Connect<Self> for MockConnector {
    fn connect(addr: SocketAddr) -> KvsResult<Self> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

还可以使用关联类型

trait Connect {
    type Connector:Communicate;
    fn connect(addr: SocketAddr) -> KvsResult<Self::Connector>;
}

impl Connect for MockConnector {
    type Connector = Self;
    fn connect(addr: SocketAddr) -> KvsResult<Self::Connector> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

当然如果你的Connect就是给Connector实现的trait,那么直接使用Self就好了,不需要显式的泛型。不过Self要一个Sized约束,且Connect不能用作trait object(你这函数里连self参数都没有,也不需要了)。

trait Connect:Sized {
    fn connect(addr: SocketAddr) -> KvsResult<Self>;
}

impl Connect for MockConnector {
    fn connect(addr: SocketAddr) -> KvsResult<Self> {
        println!("正在连接:{}", addr);
        Ok(MockConnector::new(addr))
    }
}

w 2021-03-01 14:08

我也是rust新手。因为没有看到trait Connect的定义,所以没太想出来怎么改。不过关于泛型的可以参考下源码里的一些实现,比如Vec中的:

// vec.rs:1811 
// This code generalizes `extend_with_{element,default}`.
trait ExtendWith<T> {
    fn next(&mut self) -> T;
    fn last(self) -> T;
}

struct ExtendElement<T>(T);
impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
    fn next(&mut self) -> T {
        self.0.clone()
    }
    fn last(self) -> T {
        self.0
    }
}

struct ExtendDefault;
impl<T: Default> ExtendWith<T> for ExtendDefault {
    fn next(&mut self) -> T {
        Default::default()
    }
    fn last(self) -> T {
        Default::default()
    }
}

作者 xiaoxineryi 2021-03-01 13:51

--
👇
w: 楼主引用的是哪个类库啊,找了圈没找到 是自己写的Demo,方法和对应声明就是上面的

w 2021-03-01 13:45

楼主引用的是哪个类库啊,找了圈没找到

1 共 7 条评论, 1 页