为什么我必须明确地转换为约束类型?

Jos*_*art 9 rust

为什么bar下面注释掉的代码没有编译,即使foo并且baz做到了?

use std::any::Any;
use std::fmt::Display;

// `value` implements `Clone`, so I can call `.clone()`.
fn foo<T: Display + Clone>(value: &T) {
    println!("{}", value.clone());
}

// `value` implements `Any`, so I should be able to call `.downcast_ref`...
// But this doesn't compile!
//
// fn bar<T: Display + Any>(value: &T) {
//     println!("{}", value.downcast_ref::<i32>());
// }

// For some reason I have to do an explicit cast to `&Any`...
fn baz<T: Display + Any>(value: &T) {
    let value = value as &Any;
    println!("{}", value.downcast_ref::<i32>().unwrap());
}

fn main() {
    foo(&7);
    // bar(&8);
    baz(&9);
}
Run Code Online (Sandbox Code Playgroud)

尝试编译会bar产生以下编译器错误:

error[E0599]: no method named `downcast_ref` found for type `&T` in the current scope
  --> src/main.rs:13:30
   |
13 |         println!("{}", value.downcast_ref::<i32>());
   |                              ^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

我已经详细说明了value必须实现的约束,Any为什么我必须进行显式转换?

Fra*_*gné 9

那是因为downcast_ref不是特质本身的一部分.如果我们在文档中查看特征的定义:

pub trait Any: 'static {
    fn get_type_id(&self) -> TypeId;
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到那downcast_ref不存在.只有在实现该特征的类型上才能使用定义为特征成员的方法.

相反,downcast_refimpl Any + 'static1中.由于该方法采用&self,这意味着该方法仅适用于类型的值&(Any + 'static)(&Any未指定生命周期等效&(Any + 'static)).&Any&T(哪里T是类型参数)不是同一类型; &Any是一个特征对象(它是一个胖指针),而&T它只是一个普通的引用(它是一个瘦指针).


1它也在一个impl Any + 'static + Send块中定义,因此该方法也可用于类型的值&(Any + 'static + Send).

  • 值得一提的是,`downcast_ref()`**不能成为特征的一部分:它是通用的,特征上的泛型方法使特征*不是对象安全*.这意味着如果`downcast_ref()`是特征的一部分,我们就无法创建"Any"的特征对象.这几乎会破坏"任何"的整个目的;-) (2认同)