我最近看到使用dyn关键字的代码:
fn foo(arg: &dyn Display) {}
fn bar() -> Box<dyn Display> {}
Run Code Online (Sandbox Code Playgroud)
这个语法是什么意思?
在尝试Any更好地理解这个特性的同时,我看到它有一个impl阻碍特质本身.我不明白这个结构的目的,或者即使它有一个特定的名称.
我用"普通"特征方法和impl块中定义的方法做了一个小实验:
trait Foo {
fn foo_in_trait(&self) {
println!("in foo")
}
}
impl dyn Foo {
fn foo_in_impl(&self) {
println!("in impl")
}
}
impl Foo for u8 {}
fn main() {
let x = Box::new(42u8) as Box<dyn Foo>;
x.foo_in_trait();
x.foo_in_impl();
let y = &42u8 as &dyn Foo;
y.foo_in_trait();
y.foo_in_impl(); // May cause an error, see below
}
Run Code Online (Sandbox Code Playgroud)
编者注
在Rust的版本中,包括Rust 1.15.0,该行
y.foo_in_impl()会导致错误:Run Code Online (Sandbox Code Playgroud)error: borrowed value does not live long enough --> src/main.rs:20:14 …
我有一个通用函数,打印至少两个项目:
use std::fmt::Display;
fn print_min<T: PartialOrd + Display>(a: &T, b: &T) {
println!("min = {}", if a < b { a } else { b });
}
Run Code Online (Sandbox Code Playgroud)
这适用于实现PartialOrd和Display特征的任何东西:
print_min(&45, &46);
// min = 45
print_min(&"a", &"b");
// min = a
Run Code Online (Sandbox Code Playgroud)
必须放入PartialOrd + Display函数定义是一种丑陋的,特别是如果我想拥有一大堆对此进行操作的函数(例如,实现二进制搜索树),或者我的边界变得更复杂.我的第一个倾向是尝试编写一个类型别名:
type PartialDisplay = PartialOrd + Display;
Run Code Online (Sandbox Code Playgroud)
但这给了我一些相当奇怪的编译器错误:
error[E0393]: the type parameter `Rhs` must be explicitly specified
--> src/main.rs:7:23
|
7 | type PartialDisplay = PartialOrd + Display;
| ^^^^^^^^^^ missing reference …Run Code Online (Sandbox Code Playgroud) 我有一个关联类型和通用结构的特征::
trait Generator {
type Foo;
fn generate(&self) -> Self::Foo;
}
struct Baz<A, B>
where
A: Generator,
{
generator: A, // will be some struct implementing Generator, but the exact type will vary
vec: Vec<B>, // Each element will be A::Foo
}
Run Code Online (Sandbox Code Playgroud)
我想把generate它放到我的矢量中:
impl<A: Generator, B> Baz<A, B> {
fn addFoo(&mut self) {
self.vec.push(self.generator.generate());
}
}
Run Code Online (Sandbox Code Playgroud)
嗯,哦!编译错误:
error[E0308]: mismatched types
--> src/main.rs:16:27
|
16 | self.vec.push(self.generator.generate());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type
|
= note: expected …Run Code Online (Sandbox Code Playgroud) 我有一个Trait关联类型的特征Trait::Associated.我试图通过要求它可以通过其关联类型进行索引来约束该特征,如下所示:
use std::ops::Index;
pub trait Trait: Index<Trait::Associated> {
type Associated;
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器抱怨相关类型不明确
Run Code Online (Sandbox Code Playgroud)error[E0223]: ambiguous associated type --> src/main.rs:3:24 | 3 | pub trait Trait: Index<Trait::Associated> { | ^^^^^^^^^^^^^^^^^ ambiguous associated type | = note: specify the type using the syntax `<Type as Trait>::Associated`
我也尝试将相关类型称为Self::Associated,但随后编译器抗议类型和特征之间的循环引用:
Run Code Online (Sandbox Code Playgroud)error[E0391]: cyclic dependency detected --> src/main.rs:3:1 | 3 | pub trait Trait: Index<Self::Associated> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic reference | note: the cycle begins when computing the supertraits of `Trait`... --> …
这是一个(有点人为的)例子来说明我想做什么
pub trait Node: Eq + Hash {
type Edge: Edge;
fn get_in_edges(&self) -> Vec<&Self::Edge>;
fn get_out_edges(&self) -> Vec<&Self::Edge>;
}
pub trait Edge {
type Node: Node;
fn get_src(&self) -> &Self::Node;
fn get_dst(&self) -> &Self::Node;
}
pub trait Graph {
type Node: Node;
type Edge: Edge;
fn get_nodes(&self) -> Vec<Self::Node>;
}
pub fn dfs<G: Graph>(root: &G::Node) {
let mut stack = VecDeque::new();
let mut visited = HashSet::new();
stack.push_front(root);
while let Some(n) = stack.pop_front() {
if visited.contains(n) {
continue
}
visited.insert(n); …Run Code Online (Sandbox Code Playgroud) 我有一个简单的特征,其关联类型没有边界.
trait Board {
type Move;
fn moves(&self) -> Vec<Self::Move>;
}
Run Code Online (Sandbox Code Playgroud)
我也想把这个特性用作超级特征.特别是,我希望我的新子特征对相关类型有更严格的界限.像这样的东西:
trait TextBoard: Board {
type Move: fmt::Debug; // Trying to tighten bounds on associated type
fn printMoves(&self) {
println!("{:?}", self.moves());
}
}
Run Code Online (Sandbox Code Playgroud)
这个例子是高度简化的,但似乎显示了问题:编译器认为我正在尝试创建一个新的关联类型,但我只是想让子文章需要更严格的边界.有没有办法实现这个目标?