在这种情况下,剪贴板是一个全局共享资源,当您打开它时不会给您任何令牌。在不先打开剪贴板的情况下尝试使用剪贴板将是一件坏事。如果你做了简单的事情并创建了一个空结构,那么你可以忘记调用正确的构造方法:
struct Clipboard;
impl Clipboard {
fn new() -> Clipboard {
println!("Clipboard opened");
Clipboard
}
fn copy(&self) -> String { "copied".into() }
}
let c = Clipboard::new(); // Correct
println!("{}", c.copy());
let c = Clipboard; // Nope, didn't open the clipboard properly
println!("{}", c.copy()); // But can still call methods!?!?!
让我们尝试一个内部带有虚拟值的元组结构:
struct ClipboardWithDummyTuple(());
impl ClipboardWithDummyTuple {
fn new() -> ClipboardWithDummyTuple {
println!("Clipboard opened");
ClipboardWithDummyTuple(())
}
fn copy(&self) -> String { "copied".into() }
}
let c = ClipboardWithDummyTuple::new(); // Correct
println!("{}", c.copy());
let c = ClipboardWithDummyTuple;
println!("{}", c.copy()); // Fails here
// But because `c` is a method, not an instance
这样更好,但错误发生的时间比我们希望的要晚;它仅在我们尝试使用剪贴板时发生,而不是在我们尝试构建它时发生。让我们尝试使用命名字段创建结构:
struct ClipboardWithDummyStruct {
// warning: struct field is never used
dummy: (),
}
impl ClipboardWithDummyStruct {
fn new() -> ClipboardWithDummyStruct {
println!("Clipboard opened");
ClipboardWithDummyStruct { dummy: () }
}
fn copy(&self) -> String { "copied".into() }
}
let c = ClipboardWithDummyStruct::new(); // Correct
println!("{}", c.copy());
let c = ClipboardWithDummyStruct; // Fails here
// But we have an "unused field" warning
所以,我们更接近了,但这会产生关于未使用字段的警告。我们可以使用 #[allow(dead_code)] 关闭该字段的警告,或者我们可以将该字段重命名为 _dummy,但我相信有更好的解决方案 — PhantomData:
use std::marker::PhantomData;
struct ClipboardWithPhantomData {
marker: PhantomData<()>,
}
impl ClipboardWithPhantomData {
fn new() -> ClipboardWithPhantomData {
println!("Clipboard opened");
ClipboardWithPhantomData { marker: PhantomData }
}
fn copy(&self) -> String { "copied".into() }
}
let c = ClipboardWithPhantomData::new(); // Correct
println!("{}", c.copy());
let c = ClipboardWithPhantomData; // Fails here
这不会产生任何警告,PhantomData 用于指示正在发生“不同”的事情。我可能会对结构定义发表一点评论,以说明我们为什么以这种方式使用PhantomData。
这里的很多想法都源于一个半相关的Rust issue about the correct type for an opaque struct。