在另一个包中的类型上实现std::convert::From

3
我有一个外部的 geometry crate,它定义了一个由浮点数构成的矩形结构体,还有一个外部的 sdl2 crate,它定义了一个由整数构成的矩形结构体。

以下代码展示了我期望使用 std::convert::From trait 将 geometry::Rect 转换成 sdl2::SdlRect

extern crate geometry;
extern crate sdl2;

fn main() {
    let geo_rect = geometry::Rect::default();
    let sdl_rect = sdl2::SdlRect::from(geo_rect);
}

impl From<geometry::Rect> for sdl2::SdlRect {
    fn from (rect: geometry::Rect) -> sdl2::SdlRect {
        sdl2::SdlRect {
            x: rect.x as i32,
            y: rect.y as i32,
            w: rect.w as i32,
            h: rect.h as i32,
        }
    }
}

不幸的是,这段代码无法编译,因为要么正在实现的trait或要为其实现的结构体必须来自当前crate。我发现的唯一解决方案是定义一个 MyFrom trait,它反映了 std :: convert :: From trait的功能:

extern crate geometry;
extern crate sdl2;

fn main() {
    let geo_rect = geometry::Rect::default();
    let sdl_rect = sdl2::SdlRect::my_from(geo_rect);
}

pub trait MyFrom<T> {
    fn my_from(T) -> Self;
}

impl MyFrom<geometry::Rect> for sdl2::SdlRect {
    fn my_from (rect: geometry::Rect) -> sdl2::SdlRect {
        sdl2::SdlRect {
            x: rect.x as i32,
            y: rect.y as i32,
            w: rect.w as i32,
            h: rect.h as i32,
        }
    }
}

我对这个解决方案并不是特别满意,因为在后续操作中,知道何时调用my_from而不是from会变得很混乱。有没有其他更符合Rust惯用法的解决方法?

1个回答

3

建议定义自己的矩形类型,包装外部定义的矩形,并使用标准的From特征。

这是新类型模式的一种可能用法。


新类型模式在当前的Rust中似乎还不完善——虽然有一些crate试图绕过它的限制,但就目前而言,尝试实现它是一件麻烦事,并且并没有使代码更简单。我最终做的是将my_from方法更改为from_sdl。将该方法命名为from_sdl与标准库的CStr::from_bytes方法保持一致。 - Brian
为什么不使用 impl Into<other_crate::Type> for my_crate::Type 而不是 newtype,如果您只需要执行单向转换? - Sean Pianka
链接似乎已经失效。 - MoralCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接