我如何使用一揽子 Into trait 实现来转换回原始类型?

塞索德萨

Fromtrait的文档对trait 本身和任何可能的失败有以下说明:

人们应该总是更喜欢实现FromInto因为实现会From自动提供一个实现,Into这要归功于标准库中的全面实现。

注意:这个特性不能失败。如果转换可能失败,请使用TryFrom.

我有以下From将整数转换为罗马数字的实现:

/// ### UpperRoman
/// Upper-case Roman numerals. The `None` variant is for handling invalid conversions.
pub enum UpperRoman {
    M,
    CM,
    D,
    CD,
    C,
    XC,
    L,
    XL,
    X,
    IX,
    V,
    IV,
    I,
    None,
}

impl From<u32> for UpperRoman {
    /// ### from
    /// Converts a `u32` to an `UpperRoman` numeral variant.
    fn from(numeral: u32) -> Self {
        match numeral {
            1000 => Self::M,
            900 => Self::CM,
            500 => Self::D,
            400 => Self::CD,
            100 => Self::C,
            90 => Self::XC,
            50 => Self::L,
            40 => Self::XL,
            10 => Self::X,
            9 => Self::IX,
            5 => Self::V,
            4 => Self::IV,
            1 => Self::I,
            _ => Self::None,
        }
    }
}

只有少数有效案例。对于任何无效输入,我定义了一个变体UpperRoman::None,这意味着没有罗马数字匹配给定的输入。这会处理任何故障情况,因此满足文档中设置的要求。

如果我想使用自动生成的Into-trait 实现将罗马数字转换回整数怎么办?UpperRoman::into函数如何处理这种UpperRoman::None情况?在调用函数之前,我唯一的选择是匹配可能的输入UpperRoman::into以确保它不是UpperRoman::None变体吗?

SE_net4 投票者

这里有一个混淆。鉴于您对 的实现From<u32> for UpperRoman,编译器不会自动为您提供相反的转换(即 from UpperRomanto u32)。相反,它将为您提供双重实现: Into<UpperRoman> for u32,在语义上具有相同的方向。的这种全面实现Into将允许程序员编写以下任一项:

let c = UpperRoman::from(100);
let c: UpperRoman = 100.into();

话虽如此,这意味着您需要努力进行有意义的相反转换。在这种情况下,最好假设从u32to的转换UpperRoman是一个容易出错的转换,因为并非所有整数都映射到单个罗马数字。这也将允许您删除None变体,该变体仅用作几乎不需要的“空”值,并且可以通过任何方式添加到任何类型Option

use std::convert::TryFrom;

pub enum UpperRoman {
    M,
    CM,
    D,
    CD,
    C,
    XC,
    L,
    XL,
    X,
    IX,
    V,
    IV,
    I,
}

impl TryFrom<u32> for UpperRoman {
    type Error = &'static str;

    fn try_from(numeral: u32) -> Result<Self, Self::Error> {
        match numeral {
            1000 => Ok(Self::M),
            900 => Ok(Self::CM),
            // expand the rest here
            4 => Ok(Self::IV),
            1 => Ok(Self::I),
            _ => Err("that is no good!"),
        }
    }
}

(为这种转换创建更好的错误类型留给读者作为练习。)

做完这些后,转换UpperRomanu32很简单:

impl From<UpperRoman> for u32 {
    fn from(v: UpperRoman) -> Self {
        Self::M => 1000,
        // ... expand the remaining variants exhaustively here, no None
    }
}

也可以看看:

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我不能在带有类型参数的特征上添加一揽子暗示?

提供自定义特性的一揽子特性实现

考虑您的配置定义类型“一揽子”的豆[弹簧引导]

如何从实现Trait的类型的向量创建Trait的向量?

为实现Trait的类型实现Borrow <Trait>

为另一个 trait Item 类型实现一个 trait

我如何为这个 Rust trait 使用相同的默认实现

如何为自定义错误类型实现From trait?

为什么rust debug trait的实现使用Formatter <'_>类型省略

确保我的 trait 的类型参数是 Monad

以匿名类型作为泛型参数的泛型类型实例,如何正确转换回原始类型?

Rust trait:边界可能没有实现,我实现的 trait 不存在

我如何将reflect.New的返回值转换回原始类型

如何将转换为字符串值的[[String]]转换回原始类型[[String]]?

如何从一揽子单词中找到匹配项并替换为值?

如何使用trait中的@ClosureParams引用实现者类

如何在转换为 trait 对象时使用 Rc::clone?

Rust Trait对象转换

当IndexMut需要Index时如何为自定义Trait实现Trait IndexMut,IndexMut是为自定义trait的supertrait实现的

是否可以判断一个类型是否覆盖了默认的 trait 实现?

trait 对象是如何在 Rust 中实现的?

如何为包含Rc <Refcell <Trait >>的结构实现Deref?

如何在 rust 中为泛型类型 Trait 的实现设置变量?

大熊猫的行程将列的类型更改为浮动。如何将其转换回原始类型?

如何为Box <dyn Trait>字段指定关联类型的值?

如何借用检查“impl Trait”类型的返回值?

对结构使用Trait对象-错误:类型参数的数量错误

从使用Box <Trait>强制转换的结构访问字段

强制 trait 由对象实现