3.5.5 PhantomData 与类型(实现)
05-PhantomData 与类型(实现) — Comprehensive Rust
2 分钟阅读
译文 · 基于 Comprehensive Rust
3.5.5 PhantomData 与类型(实现)
通过添加类型参数来解决上一页的问题。
| |
这里我们使用类型参数,并将权限关在实现不同权限 trait 的「标签」类型后面。
标签类型(或标记类型)是零大小类型,对用户与 API 设计者有某种语义含义。
提问:让它成为该类型的实际实例会带来什么问题?
答:若它不是零大小类型(如
()或struct MyTag;),那么当我们只关心仅在编译期相关的类型信息时,会分配比需要更多的内存。演示:完全去掉
tag值,然后编译!这不会编译,因为有一个未使用的(phantom)类型参数。
这正是
PhantomData出场之处!演示:取消注释
PhantomData导入,并将ChatId<T>改为如下:
1 2 3 4 5 6 7// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 # pub struct ChatId<T> { id: u64, tag: PhantomData<T>, }
PhantomData<T>是带类型参数的零大小类型。我们可以像其他 ZST 一样构造它的值:let phantom: PhantomData<UserTag> = PhantomData;,或使用PhantomData::default()实现。演示:为
ChatId<T>实现From<u64>,强调PhantomData的构造
1 2 3 4 5 6 7 8 9 10 11 12// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 # impl<T> From<u64> for ChatId<T> { fn from(value: u64) -> Self { ChatId { id: value, // 或 `PhantomData::default()` tag: PhantomData, } } }
PhantomData可作为 Typestate 模式的一部分,使数据具有相同结构但不同方法,例如让TaggedData<Start>实现TaggedData<End>没有的方法或 trait 实现。