是否可以将特征中的函数定义为具有impl Trait
返回类型?我想创建一个可以由多个结构实现的特征,以便所有这些特征的new()
函数返回一个对象,它们都可以以相同的方式使用,而不必编写特定于每个结构的代码。
#![feature(conservative_impl_trait)]
trait A {
fn new() -> impl A;
}
但是,我收到以下错误:
impl Trait
不允许在函数和固有方法返回类型之外
这仅仅是Rust当前执行impl Trait
的限制还是我使用它错了?
如果您只需要返回当前正在实施特征的特定类型,您可能正在寻找Self
。
trait A {
fn new() -> Self;
}
例如,这将编译:
trait A {
fn new() -> Self;
}
struct Person;
impl A for Person {
fn new() -> Person {
Person
}
}
或者,更完整的例子,展示使用特征:
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()
}
作为旁注..我在这里使用String
赞成&str
引用..减少对显性生命期的需要,并可能失去对手头问题的关注。我相信通常的惯例是在借用内容时返回&str
引用,这似乎是合适的..但是我不想过多地分散实际的例子。
作为trentcl mentions,你现在不能将impl Trait
放在特征方法的返回位置。
来自RFC 1522:
impl Trait
只能在独立或固有impl函数的返回类型中编写,而不能在特征定义或任何非返回类型位置编写。它们也可能不会出现在闭包特征或函数指针的返回类型中,除非它们本身是合法返回类型的一部分。
- 最终,我们希望允许在特征中使用该特征[...]
现在,您必须使用盒装特征对象:
trait A {
fn new() -> Box<dyn A>;
}
也可以看看:
如果你想使用不稳定的夜间功能,你可以使用existential types (RFC 2071):
#![feature(existential_type)]
trait FromTheFuture {
type Iter: Iterator<Item = u8>;
fn example(&self) -> Self::Iter;
}
impl FromTheFuture for u8 {
existential type Iter: 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);
}
}
通过显式命名返回类型,即使在没有返回“Self”的情况下,您也可以获得类似的东西。
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
}
}