提问人:exocortex 提问时间:2/1/2023 更新时间:2/1/2023 访问量:65
如何为返回正确类型的枚举实现 get-method?
How do I implement a get-method for an enum that returns the right type?
问:
我有一个枚举,其中包含包含某些类型的变体。我想编写一个方法,如果枚举变体包含此类型,则该方法会自动返回正确的类型。get
pub enum Var {
Switch(bool),
PositiveInteger(u32),
Integer(i32),
PositiveFloat(f64),
Float(f64),
Phase(f64), // a float x, where 0.0 <= x < 2Pi
Turn(f64), // the same, but with 0.0 <= x < 1.0
}
在代码的其他地方,我想获取变体的内部,例如.但是(对我来说)似乎不可能编写一个泛型函数,如下所示:value
PositiveFloat( value )
impl Var {
pub fn get<T>(&self) -> T
where
T: Default,
{
match self {
Var::Switch(value) => value,
Var::PositiveInteger(value) => value,
// etc
}
相反,我似乎必须为枚举的每个变体实现不同的 get-method:、 等。
也许我以错误的方式看待问题。我想实现这样的目标:get_positive_integer()
get_integer()
let positive_integer = Var::PositiveInteger(1);
let x: u32 = positive_integer.get();
let float = Var::Float(0.1);
let y: f64 = float.get();
答:
3赞
Chayim Friedman
2/1/2023
#1
您可以为此创建一个特征:
pub trait VarTypes: Sized {
fn get(var: &Var) -> Option<Self>;
}
impl VarTypes for bool {
fn get(var: &Var) -> Option<Self> {
match *var {
Var::Switch(v) => Some(v),
_ => None,
}
}
}
impl VarTypes for u32 {
fn get(var: &Var) -> Option<Self> {
match *var {
Var::PositiveInteger(v) => Some(v),
_ => None,
}
}
}
impl VarTypes for i32 {
fn get(var: &Var) -> Option<Self> {
match *var {
Var::Integer(v) => Some(v),
_ => None,
}
}
}
impl VarTypes for f64 {
fn get(var: &Var) -> Option<Self> {
match *var {
Var::PositiveFloat(v) | Var::Float(v) | Var::Phase(v) | Var::Turn(v) => Some(v),
_ => None,
}
}
}
然后,你可以用它实现:get()
impl Var {
pub fn get<T>(&self) -> T
where
T: VarTypes + Default,
{
T::get(self).unwrap_or_default()
}
}
评论
0赞
exocortex
2/3/2023
谢谢!这很有帮助。我在这里没有想到特质。
3赞
cafce25
2/1/2023
#2
不能直接定义方法,因为每种类型都需要不同的实现。相反,您可以做的是定义一个通用特征,并为所需的每种类型实现该特征:impl Var
trait Get<T> {
fn get(&self) -> Option<T>;
}
impl Get<bool> for Var {
fn get(&self) -> Option<bool> {
match self {
Var::Switch(value) => Some(*value),
_ => None,
}
}
}
impl Get<u32> for Var {
fn get(&self) -> Option<u32> {
match self {
Var::PositiveInteger(v) => Some(*v),
_ => None,
}
}
}
impl Get<f64> for Var {
fn get(&self) -> Option<f64> {
match self {
Var::PositiveFloat(v) | Var::Float(v) | Var::Phase(v) | Var::Turn(v) => Some(*v),
_ => None,
}
}
}
// …
我将返回类型更改为 因为它放宽了对的要求,并且更符合其他类似方法 (, ...) 并且您可以通过简单的语义重新获得语义:Option<T>
T
slice::get
unwrap_or_default()
let positive_integer = Var::PositiveInteger(1);
let x: u32 = positive_integer.get().unwrap_or_default();
评论
0赞
exocortex
2/3/2023
谢谢!我在这里和你一样使用它,效果非常好。还有错误处理。匪夷所思!
评论