为闭包类型别名实现特征
Implement trait for closure type alias
我有这个闭包类型的别名:
type ClosureType = Box<Fn(i32) -> i32>;
这个特质:
trait Trait {
fn change(&self, y: i32) -> i32;
}
以及这些函数:
fn with_one(x: Box<Fn(i32) -> i32>) -> i32 {
x(1)
}
fn plus_one(x: i32) -> i32 {
x+1
}
fn main() {
let a = Box::new(|x: i32|{x+1});
let b: ClosureType = Box::new(|x: i32|{x+1});
let c = Box::new(plus_one);
let d: ClosureType = Box::new(plus_one);
println!("{}", a.change(1));
println!("{}", b.change(1));
println!("{}", c.change(1));
println!("{}", d.change(1));
println!("{}", with_one(a));
println!("{}", with_one(b));
println!("{}", with_one(c));
println!("{}", with_one(d));
}
当我为 ClosureType
或 Box<Fn(i32) -> i32>
实现特征 Trait
时,如果我理解正确,类型别名是相同的:
impl Trait for ClosureType {
fn change(&self, y: i32) -> i32{
self(y)
}
}
或
impl Trait for Box<Fn(i32) -> i32> {
fn change(&self, y: i32) -> i32{
self(y)
}
}
对于变量 a
我得到:
<anon>:32:22: 32:31 error: no method named `change` found for type
`Box<[closure <anon>:28:22: 28:35]>` in the current scope
<anon>:32 println!("{}", a.change(1));
对于变量 c
我得到:
<anon>:34:22: 34:31 error: no method named `change` found for type
`Box<fn(i32) -> i32 {plus_one}>` in the current scope
<anon>:34 println!("{}", c.change(1));
然而变量a
和c
从函数with_one(x: Box<Fn(i32) -> i32>) -> i32
接受,换句话说,它们似乎具有相同的类型(Box<Fn(i32) -> i32>
)对于函数with_one
但对于 Trait
实现不同(Box<[closure <anon>:24:22: 24:35]>
和 Box<fn(i32) -> i32 {plus_one}
)。
我觉得我在这里遗漏了一些东西但不确定它是什么,你能告诉我吗?
您可以在this rust playground中找到所有代码。
我相信这是由于从具体类型到特征对象类型的自动强制转换(即不存在)造成的。
当您调用 with_one()
时,编译器能够从函数参数类型中理解您需要特征对象,因此它会插入自动强制转换:
with_one(a as Box<Fn(i32) -> i32>);
with_one(c as Box<Fn(i32) -> i32>);
对于 b
和 d
,这些强制已在 let
秒内在他们的分配位置发生。
但是,对于特征方法,编译器不执行强制转换。这是泛型的常见行为(特征是通过泛型实现的——它们的 Self
类型本质上是所有特征方法的隐式类型参数)。例如,Rust 在使用泛型时也不执行 deref 强制转换:
trait MyStringLike {}
impl<'a> MyStringLike for &'a str {}
fn function<T: MyStringLike>(t: T) {}
let s: String = "abcde".into();
function(&s); // the trait `main::MyStringLike` is not implemented for the type `&collections::string::String`
我有这个闭包类型的别名:
type ClosureType = Box<Fn(i32) -> i32>;
这个特质:
trait Trait {
fn change(&self, y: i32) -> i32;
}
以及这些函数:
fn with_one(x: Box<Fn(i32) -> i32>) -> i32 {
x(1)
}
fn plus_one(x: i32) -> i32 {
x+1
}
fn main() {
let a = Box::new(|x: i32|{x+1});
let b: ClosureType = Box::new(|x: i32|{x+1});
let c = Box::new(plus_one);
let d: ClosureType = Box::new(plus_one);
println!("{}", a.change(1));
println!("{}", b.change(1));
println!("{}", c.change(1));
println!("{}", d.change(1));
println!("{}", with_one(a));
println!("{}", with_one(b));
println!("{}", with_one(c));
println!("{}", with_one(d));
}
当我为 ClosureType
或 Box<Fn(i32) -> i32>
实现特征 Trait
时,如果我理解正确,类型别名是相同的:
impl Trait for ClosureType {
fn change(&self, y: i32) -> i32{
self(y)
}
}
或
impl Trait for Box<Fn(i32) -> i32> {
fn change(&self, y: i32) -> i32{
self(y)
}
}
对于变量 a
我得到:
<anon>:32:22: 32:31 error: no method named `change` found for type
`Box<[closure <anon>:28:22: 28:35]>` in the current scope
<anon>:32 println!("{}", a.change(1));
对于变量 c
我得到:
<anon>:34:22: 34:31 error: no method named `change` found for type
`Box<fn(i32) -> i32 {plus_one}>` in the current scope
<anon>:34 println!("{}", c.change(1));
然而变量a
和c
从函数with_one(x: Box<Fn(i32) -> i32>) -> i32
接受,换句话说,它们似乎具有相同的类型(Box<Fn(i32) -> i32>
)对于函数with_one
但对于 Trait
实现不同(Box<[closure <anon>:24:22: 24:35]>
和 Box<fn(i32) -> i32 {plus_one}
)。
我觉得我在这里遗漏了一些东西但不确定它是什么,你能告诉我吗?
您可以在this rust playground中找到所有代码。
我相信这是由于从具体类型到特征对象类型的自动强制转换(即不存在)造成的。
当您调用 with_one()
时,编译器能够从函数参数类型中理解您需要特征对象,因此它会插入自动强制转换:
with_one(a as Box<Fn(i32) -> i32>);
with_one(c as Box<Fn(i32) -> i32>);
对于 b
和 d
,这些强制已在 let
秒内在他们的分配位置发生。
但是,对于特征方法,编译器不执行强制转换。这是泛型的常见行为(特征是通过泛型实现的——它们的 Self
类型本质上是所有特征方法的隐式类型参数)。例如,Rust 在使用泛型时也不执行 deref 强制转换:
trait MyStringLike {}
impl<'a> MyStringLike for &'a str {}
fn function<T: MyStringLike>(t: T) {}
let s: String = "abcde".into();
function(&s); // the trait `main::MyStringLike` is not implemented for the type `&collections::string::String`