Rust 特征与类型限制

发布于 2025-01-13 15:55:20 字数 728 浏览 3 评论 0原文

我想使用 Rust 特征编写数据库的基本抽象。

pub trait Keyable {
    type Key;
    fn key(&self) -> &Self::Key;
}

// type alias for result - DbError are defined elsewhere
pub type Result<T> = Result<T, DbError>;

pub trait Database {
    type Item;

    fn get(&self, id: Keyable) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<Keyable>;
}

正在努力表达这一点:Database::Item 必须至少是 Keyable 的。

有两个用例:

  1. 我可以使用一些任意类型,它知道如何在我的 Database::get(k: Keyable) 函数中返回 key() ,但返回一些 Item (这可能不仅仅是 在我的 fn Database::upsert( )
  2. 函数中,我希望能够使用该项目至少是 Keyable 的事实,因此如果我只是简单地访问 key() 来查找数据库以做出决定插入或更新。

I want to write a basic abstraction of a database, using Rust traits.

pub trait Keyable {
    type Key;
    fn key(&self) -> &Self::Key;
}

and

// type alias for result - DbError are defined elsewhere
pub type Result<T> = Result<T, DbError>;

pub trait Database {
    type Item;

    fn get(&self, id: Keyable) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<Keyable>;
}

I am struggling to express this: Database::Item must be at least Keyable.

There are two use cases:

  1. I can use some arbitrary type which knows how to return a key() in my Database::get(k: Keyable) function and yet return some Item (which is likely to have quite a bit more than just the key().
  2. In my fn Database::upsert() function, I want to be able to use the fact that the item is at least Keyable and therefore access the key() to lookup the database to make a decision if I simply insert or update.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城泪 2025-01-20 15:55:20

您可以在关联类型上放置特征绑定:

pub trait Database {
    type Item: Keyable;

然后,您可以在函数签名中使用该特征的关联类型:(

    fn get(&self, id: &<Self::Item as Keyable>::Key) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<<Self::Item as Keyable>::Key>;

我还添加了 & 因为 get() 可能不需要使用关键数据。)

将它们全部放在一个可编译的示例中:

pub enum DbError { Something }
pub type Result<T> = std::result::Result<T, DbError>;

pub trait Keyable {
    type Key;
    fn key(&self) -> &Self::Key;
}

pub trait Database {
    type Item: Keyable;

    fn get(&self, id: &<Self::Item as Keyable>::Key) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<<Self::Item as Keyable>::Key>;
}

You can place a trait bound on an associated type:

pub trait Database {
    type Item: Keyable;

Then, you can use that trait's associated type(s) in function signatures:

    fn get(&self, id: &<Self::Item as Keyable>::Key) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<<Self::Item as Keyable>::Key>;

(I also added an & because get() probably shouldn't be required to consume the key data.)

Putting that all together to a compilable example:

pub enum DbError { Something }
pub type Result<T> = std::result::Result<T, DbError>;

pub trait Keyable {
    type Key;
    fn key(&self) -> &Self::Key;
}

pub trait Database {
    type Item: Keyable;

    fn get(&self, id: &<Self::Item as Keyable>::Key) -> Result<Self::Item>;    
    fn upsert(&self, item: Self::Item) -> Result<<Self::Item as Keyable>::Key>;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文