我不确定如何准确地提出这个问题,所以我会通过例子来说明。
我正在使用 bitflags 板条箱,它提供了一个名为
Flags
的特征。标志特征涉及关联类型的存在,例如
pub trait Flags: Sized + 'static {
/// The underlying bits type.
type Bits: Bits;
fn from_bits(bits: Self::Bits) -> Option<Self> {
...
}
...
}
其中 Bits 特征是为以下内容实现的
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
然后我希望定义一个继承 Flags 的特征 (
Register
),但添加了在实现时定义关联常量的要求。类似的东西
trait Register: Flags {
const ADDRESS: u8;
fn address(&self) -> u8 {
Self::ADDRESS
}
}
访问带有附加地址的
Flags
将允许我做一些有用的事情,但是其中一些有用的事情依赖于 Flags 实现来使 Bits
类型成为 u8
。我最终陷入了这样的境地
trait Register: Flags {
const ADDRESS: u8;
fn address(&self) -> u8 {
Self::ADDRESS
}
fn do_something(&self) {
let new_bits_data: u8 = ...;
*self = Self::from_bits(new_bits_data).unwrap()
}
}
调用
Self::from_bits()
不起作用,因为我们还不知道 Flags
的特定实现将具有的位的类型。
在我看来,我希望能够仅为已设置的
Register
实现的子集定义Flags
特征
type Bits = u8;
但我不知道这是否是个好主意,甚至可能。
您对我如何解决这个问题有什么想法,或者是否可以实现我想要的?
我考虑过定义一个特质
Flags_u8
的想法,它与 Flags
相同,但约束为 Bits
类型是 u8
。但我不知道那会是什么样子。
您可以限制超级特征的关联类型,类似于对任何特征所做的操作:
trait Register: Flags<Bits = u8> { ... }
或者具体方法:
trait Register: Flags {
const ADDRESS: u8;
fn address(&self) -> u8 {
Self::ADDRESS
}
fn do_something(&self)
where
Self: Flags<Bits = u8>,
{
let new_bits_data: u8 = ...;
*self = Self::from_bits(new_bits_data).unwrap()
}
}