首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rust是否有一种使用默认关联类型的方法?

Rust是否有一种使用默认关联类型的方法?
EN

Stack Overflow用户
提问于 2021-05-03 21:15:20
回答 1查看 298关注 0票数 1

https://stackoverflow.com/a/65924807/5884503之后,我将添加关联类型,以便从我的特性方法返回期货:

代码语言:javascript
复制
pub trait RtspClient: Runnable {
    type PlayResult: Future<Output = std::result::Result<(), ()>>;
    type ConnectResult: Future<Output = std::result::Result<(), RtspConnectionError>>;
    type DisconnectResult: Future<Output = std::result::Result<(), RtspDisconnectionError>>;

    fn connect(&self) -> RtspClient::ConnectResult {
        Ok(())
    }

    fn disconnect(&self) ->  RtspClient::DisconnectResult {
        Ok(())
    }
}

但是,我添加的方法越多,得到的关联类型就越多。

这不是一个问题,只是当我需要使用dyn RtspClient时,我需要指定所有这些

代码语言:javascript
复制
  |
12 |     pub rtsp_client: Option<Arc<Mutex<dyn RtspClient>>>,
   |                                           ^^^^^^^^^^ help: specify the associated types: `RtspClient<PlayResult = Type, ConnectResult = Type, DisconnectResult = Type>`
   | 

有没有办法强迫铁锈使用我在特征定义中已经写过的默认方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-04 01:14:00

这里有很多误解。关联类型的Future<...>部分不是默认的,而是一个约束。Future不是一种类型,而是一种特征。例如,它的意思是实现的PlayResult必须满足Future<...>约束。

默认关联类型如下所示:

代码语言:javascript
复制
pub trait RtspClient  {
    type PlayResult = Ready<Result<(), ()>>; // using std::future::Ready as an example
}

但是这个语法还没有稳定下来:

代码语言:javascript
复制
error[E0658]: associated type defaults are unstable
 --> src/lib.rs:4:5
  |
4 |     type PlayResult = Ready<Result<(), ()>>; // using std::future::Ready as an example
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #29661 <https://github.com/rust-lang/rust/issues/29661> for more information

而且,即使您使用夜间编译器并启用该特性,默认情况下也无法实现connect()disconnect(),因为它必须对所有可能的实现都有效(在某些情况下可以这样做,但我认为这不是其中之一):

代码语言:javascript
复制
error[E0308]: mismatched types
  --> src/lib.rs:13:9
   |
12 |     fn connect(&self) -> Self::ConnectResult {
   |                          ------------------- expected `<Self as RtspClient>::ConnectResult` because of return type
13 |         ready(Ok(()))
   |         ^^^^^^^^^^^^^ expected associated type, found struct `std::future::Ready`
   |
   = note: expected associated type `<Self as RtspClient>::ConnectResult`
                       found struct `std::future::Ready<Result<(), _>>`

error[E0308]: mismatched types
  --> src/lib.rs:17:9
   |
16 |     fn disconnect(&self) ->  Self::DisconnectResult {
   |                              ---------------------- expected `<Self as RtspClient>::DisconnectResult` because of return type
17 |         ready(Ok(()))
   |         ^^^^^^^^^^^^^ expected associated type, found struct `std::future::Ready`
   |
   = note: expected associated type `<Self as RtspClient>::DisconnectResult`
                       found struct `std::future::Ready<Result<(), _>>`

即使这确实有效,你也会很难把它作为一个特征对象使用。每个实现都可以有不同的具体关联类型,但是您需要指定具体的关联类型来使用它作为一个属性对象。它们无疑将无法与之相匹配:

代码语言:javascript
复制
struct MyDefaultClient;

impl RtspClient for MyDefaultClient {
    // just uses the default types
    
    fn connect(&self) -> Self::ConnectResult {
        ready(Ok(()))
    }
    
    fn disconnect(&self) -> Self::DisconnectResult {
        ready(Ok(()))
    }
}

struct MyCustomClient;

impl RtspClient for MyCustomClient {
    type ConnectResult = Pending<Result<(), RtspConnectionError>>; // different associated types
    type DisconnectResult = Pending<Result<(), RtspDisconnectionError>>;
    
    fn connect(&self) -> Self::ConnectResult {
        pending()
    }
    
    fn disconnect(&self) -> Self::DisconnectResult {
        pending()
    }
}

fn main() {
    let data = [
        Box::new(MyDefaultClient) as Box<dyn RtspClient<ConnectResult = _, DisconnectResult = _>>,
        Box::new(MyCustomClient),
    ];
}

_部件允许编译器推断正确的类型,但会产生错误,因为dyn RtspClient<ConnectResult = A, ...>dyn RtspClient<ConnectResult = B>不同。

代码语言:javascript
复制
error[E0271]: type mismatch resolving `<MyDefaultClient as RtspClient>::DisconnectResult == std::future::Pending<Result<(), RtspDisconnectionError>>`
  --> src/main.rs:48:9
   |
48 |         Box::new(MyDefaultClient) as Box<dyn RtspClient<ConnectResult = _, DisconnectResult = _>>,
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::future::Pending`, found struct `std::future::Ready`
   |
   = note: expected struct `std::future::Pending<Result<(), RtspDisconnectionError>>`
              found struct `std::future::Ready<Result<(), RtspDisconnectionError>>`
   = note: required for the cast to the object type `dyn RtspClient<DisconnectResult = std::future::Pending<Result<(), RtspDisconnectionError>>, ConnectResult = std::future::Pending<Result<(), RtspConnectionError>>>`

error[E0271]: type mismatch resolving `<MyDefaultClient as RtspClient>::ConnectResult == std::future::Pending<Result<(), RtspConnectionError>>`
  --> src/main.rs:48:9
   |
48 |         Box::new(MyDefaultClient) as Box<dyn RtspClient<ConnectResult = _, DisconnectResult = _>>,
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::future::Pending`, found struct `std::future::Ready`
   |
   = note: expected struct `std::future::Pending<Result<(), RtspConnectionError>>`
              found struct `std::future::Ready<Result<(), RtspConnectionError>>`
   = note: required for the cast to the object type `dyn RtspClient<DisconnectResult = std::future::Pending<Result<(), RtspDisconnectionError>>, ConnectResult = std::future::Pending<Result<(), RtspConnectionError>>>`

关联类型和特征对象不会以这种方式混在一起。您可以将它们视为常规泛型类型:Struct<A>是与Struct<B>完全不同的类型。

如果您想要交替地使用不同的实现,您应该遵循链接答案中的其他建议,并使用装箱期货、Pin<Box<Future<...>>>或助手crate async-trait,而不是使用关联类型。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67375914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档