考虑一个需要实现特定清理方法的特征,并确保在删除实例时实际执行此清理。我们可以写这样的东西:
trait MyTrait {
fn cleanup(&self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn cleanup(&self) {
println!("Cleaning up");
}
}
impl Drop for MyStruct {
fn drop(&mut self) {
<Self as MyTrait>::cleanup(self);
}
}
fn main() {
{
let x = MyStruct;
}
println!("done");
}
并且它会起作用,但它不会强制在
Drop
上实现 MyStruct
,并且可能很容易被忽略。
有没有一种方法可以确保或提供 MyTrait
调用 drop()
的默认实现?cleanup()
用户可以通过
mod library {
pub trait MyTraitImpls {
fn cleanup(&self);
}
/// Users are forbidden from implementing this.
#[doc(hidden)]
pub trait __Private {}
/// Implement via `MyTraitImpls` and `impl_my_trait!(...)`
pub trait MyTrait: MyTraitImpls + __Private {}
impl<T: MyTraitImpls + __Private> MyTrait for T {}
#[macro_export]
macro_rules! impl_my_trait {
($name: ident) => {
impl library::__Private for $name {}
impl Drop for $name {
fn drop(&mut self) {
<Self as library::MyTraitImpls>::cleanup(self);
}
}
}
}
}
use crate::library::*;
struct MyStruct;
impl MyTraitImpls for MyStruct {
fn cleanup(&self) {
println!("Cleaning up");
}
}
impl_my_trait!(MyStruct);
绕过这个,但至少你不会意外地这样做。