在https://stackoverflow.com/a/65924807/5884503之后,我将添加关联类型,以便从我的特性方法返回期货:
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时,我需要指定所有这些
|
12 | pub rtsp_client: Option<Arc<Mutex<dyn RtspClient>>>,
| ^^^^^^^^^^ help: specify the associated types: `RtspClient<PlayResult = Type, ConnectResult = Type, DisconnectResult = Type>`
| 有没有办法强迫铁锈使用我在特征定义中已经写过的默认方法?
发布于 2021-05-04 01:14:00
这里有很多误解。关联类型的Future<...>部分不是默认的,而是一个约束。Future不是一种类型,而是一种特征。例如,它的意思是实现的PlayResult必须满足Future<...>约束。
默认关联类型如下所示:
pub trait RtspClient {
type PlayResult = Ready<Result<(), ()>>; // using std::future::Ready as an example
}但是这个语法还没有稳定下来:
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(),因为它必须对所有可能的实现都有效(在某些情况下可以这样做,但我认为这不是其中之一):
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<(), _>>`即使这确实有效,你也会很难把它作为一个特征对象使用。每个实现都可以有不同的具体关联类型,但是您需要指定具体的关联类型来使用它作为一个属性对象。它们无疑将无法与之相匹配:
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>不同。
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,而不是使用关联类型。
https://stackoverflow.com/questions/67375914
复制相似问题