Is it possible to use `impl Trait` as a function's return type in a trait definition?
是否可以将特征内部的函数定义为具有
1 2 3 | trait A { fn new() -> impl A; } |
但是,出现以下错误:
1 2 3 4 5 | error[E0562]: `impl Trait` not allowed outside of function and inherent method return types --> src/lib.rs:2:17 | 2 | fn new() -> impl A; | ^^^^^^ |
这是对
如trentcl所述,您当前不能将
根据RFC 1522:
impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.
- Eventually, we will want to allow the feature to be used within traits [...]
现在,您必须使用一个装箱的特征对象:
1 2 3 | trait A { fn new() -> Box<dyn A>; } |
也可以看看:
- 是否可以在特征中具有构造函数?
- 为什么特质不能自我构建?
- 如何从方法返回特征的实例?
仅每晚
如果您希望使用不稳定的夜间功能,则可以使用存在类型(RFC 2071):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 1.40.0-nightly (2019-11-05 1423bec54cf2db283b61) #![feature(type_alias_impl_trait)] trait FromTheFuture { type Iter: Iterator<Item = u8>; fn example(&self) -> Self::Iter; } impl FromTheFuture for u8 { type Iter = impl Iterator<Item = u8>; fn example(&self) -> Self::Iter { std::iter::repeat(*self).take(*self as usize) } } fn main() { for v in 7.example() { println!("{}", v); } } |
如果仅需要返回当前正在为其实现特征的特定类型,则可能正在寻找
1 2 3 | trait A { fn new() -> Self; } |
例如,它将编译:
1 2 3 4 5 6 7 8 9 10 11 | trait A { fn new() -> Self; } struct Person; impl A for Person { fn new() -> Person { Person } } |
或者,举一个更完整的示例,使用该特征进行演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | trait A { fn new<S: Into<String>>(name: S) -> Self; fn get_name(&self) -> String; } struct Person { name: String } impl A for Person { fn new<S: Into<String>>(name: S) -> Person { Person { name: name.into() } } fn get_name(&self) -> String { self.name.clone() } } struct Pet { name: String } impl A for Pet { fn new<S: Into<String>>(name: S) -> Pet { Pet { name: name.into() } } fn get_name(&self) -> String { self.name.clone() } } fn main() { let person = Person::new("Simon"); let pet = Pet::new("Buddy"); println!("{}'s pets name is {}", get_name(&person), get_name(&pet)); } fn get_name<T: A>(a: &T) -> String { a.get_name() } |
操场
附带说明..我在这里使用
通过使用关联类型并显式命名返回类型,即使在不返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | trait B {} struct C; impl B for C {} trait A { type FReturn: B; fn f() -> Self::FReturn; } struct Person; impl A for Person { type FReturn = C; fn f() -> C { C } } |
对Rust来说还很陌生,因此可能需要检查。
您可以对返回类型进行参数化。这是有限制的,但是它们比简单地返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | trait A< T > where T: A< T > { fn new() -> T; } // return a Self type struct St1; impl A<St1> for St1 { fn new() -> St1 { St1 } } // return a different type struct St2; impl A<St1> for St2 { fn new() -> St1 { St1 } } // won't compile as u32 doesn't implement A<u32> struct St3; impl A<u32> for St3 { fn new() -> u32 { 0 } } |
这种情况下的限制是,您只能返回实现
1 2 | impl A<St1> for St2 ... impl A<St2> for St1 ... |
为此,您需要进一步限制类型,例如
1 2 3 | trait A<T, U> where U: A<T, U>, T: A<U, T> { fn new() -> T; } |
但我在努力争取最后一个。