热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

类型构造函数实现Fn吗?

如何解决《类型构造函数实现Fn吗?》经验,为你挑选了1个好方法。

我不确定问题的标题是否正确,因为我不确定确切的位置。假设我有一个看起来像这样的代码:


struct MyWrapper(u64);

fn my_func(f: F, n: u64) -> MyWrapper
where
    F: Fn(u64) -> MyWrapper,
{
    f(n)
}

fn main() {
    my_func(MyWrapper, 3);
}

它可以编译和工作,因此看起来像是MyWrapper实现了特质Fn

但是,我应该尝试在特征中使用它吗?

struct MyWrapper(u64);

trait MyTrait
where
    Self: Fn(u64) -> MyWrapper,
{
}

impl MyTrait for MyWrapper{}

我得到一个错误

16 | impl MyTrait for MyWrapper{};
   |      ^^^^^^^ expected an `Fn<(u64,)>` closure, found `MyWrapper`
   |
   = help: the trait `std::ops::Fn<(u64,)>` is not implemented for `MyWrapper`

这是一个更具理论性的问题。

说实话,我想要实现的是实现这样的特质

编辑:我正确地指出我的示例不完整,因此有一个固定版本。

pub enum Status {
    New,
    Cancelled,
}

struct NewTransaction(u64);

struct CancelledTransaction(u64);

fn get_by_status(id: &str, status: Status) -> Result {
    Ok(3)
}

pub trait Transaction
where
    Self: std::marker::Sized,
{
    const status: Status;
    fn get(id: &str) -> Result;
}

impl Transaction for NewTransaction {
    const status: Status = Status::New;
    fn get(id: &str) -> Result {
        get_by_status(id, Self::status).map(Self)
    }
}

impl Transaction for CancelledTransaction {
    const status: Status = Status::Cancelled;
    fn get(id: &str) -> Result {
        get_by_status(id, Self::status).map(Self)
    }
}

该代码可以编译,但是正如您所看到的-每种类型的Transaction的所有实现都是完全相同的,因此将这种实现作为默认设置似乎是完全合理的。像这样

16 | impl MyTrait for MyWrapper{};
   |      ^^^^^^^ expected an `Fn<(u64,)>` closure, found `MyWrapper`
   |
   = help: the trait `std::ops::Fn<(u64,)>` is not implemented for `MyWrapper`

我在这里抱怨自己不能被用作价值。我试图通过引入where Self: Fn(u32) -> Self特征条件来解决此问题,但是它也不起作用。

编辑:最后,我实现了Sven Marnach提出的想法-添加了一个方法,new并要求所有结构都可以实现此方法。看起来仍然很奇怪,因为所有结构的实现都是完全相同的,但是可以工作。

pub enum Status {
    New,
    Cancelled,
}

struct NewTransaction(u64);

struct CancelledTransaction(u64);

fn get_by_status(id: &str, status: Status) -> Result {
    Ok(3)
}

pub trait Transaction
where
    Self: std::marker::Sized,
{
    const status: Status;
    fn get(id: &str) -> Result;
}

impl Transaction for NewTransaction {
    const status: Status = Status::New;
    fn get(id: &str) -> Result {
        get_by_status(id, Self::status).map(Self)
    }
}

impl Transaction for CancelledTransaction {
    const status: Status = Status::Cancelled;
    fn get(id: &str) -> Result {
        get_by_status(id, Self::status).map(Self)
    }
}

谢谢大家的回答!



1> Sven Marnach..:

当在期望值而不是类型的上下文中使用时,类似元组的struct或enum变体的构造函数实际上被视为函数名称,并且在期望类型的上下文中将其视为其命名的类型。

调用时my_func(MyWrapper, 3),名称MyWrapper表示具有强制转换为函数指针类型的函数项类型的函数fn(u64) -> MyWrapper。特别地,item类型实现了trait Fn(u64) -> MyWrapper

impl MyTrait for MyWrapper {}但是,在代码中MyWrapper表示其声明的struct类型。该类型与MyWrapper在值上下文中使用时的类型完全不同,并且不实现Fn(u64) -> MyWrapper特征。

在您的实际用例中,我相信最简单的解决方案是new()在类型上需要一种具有所需原型的方法:

trait Payment {
   const status: Status;
   fn new(x: u64) -> Self;
   fn get(id: u64) -> Result {
       get_by_status(Self::status, id).map(Self::new)
   }
}

的实现者Payment将只需要为new()方法提供所需的原型,而将继承的默认实现get()


推荐阅读
author-avatar
JRamboKing
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有