当前位置: 首页 > 知识库问答 >
问题:

Rust box 包含通用特征的单一特征

韩羽
2023-03-14

我的情况是,我希望一些对象实现一个特征,比如说“基本”,而其他一些对象将实现一个特征“超级”。Super trait还必须是< code>T : Base的泛型,这样我就可以根据它所专用的Base自动实现Super的各个部分。现在,这似乎可以很好地处理下面的小例子

trait Base {
    fn say_hi() -> &'static str;
}

struct BaseOne {}
struct BaseTwo {}

impl Base for BaseOne {
    fn say_hi() -> &'static str {
        "hi!"
    }
}

impl Base for BaseTwo {
    fn say_hi() -> &'static str {
        "hello!"
    }
}

trait Super<T: Base> {
    fn say_hi(&self) -> &'static str {
        T::say_hi()
    }
}

struct SuperOne;
struct SuperTwo;

impl Super<BaseOne> for SuperOne {}
impl Super<BaseTwo> for SuperTwo {}

我的问题与我的下一个要求有关,那就是我希望能够存储实现Super的对象向量,而不管它专门用于哪个Base。我的想法是创建一个涵盖所有超能力者的特征,例如下面的AnySuper特征

trait AnySuper {
    fn say_hi(&self) -> &'static str;
}

impl<T> AnySuper for dyn Super<T> where T : Base {
    fn say_hi(&self) -> &'static str {
        Super::say_hi(self)
    }
}

然后存储Box的向量,如下例所示

fn main() {
    let one = Box::new(SuperOne);
    let two = Box::new(SuperTwo);
    
    let my_vec: Vec<Box<dyn AnySuper>> = Vec::new();
    
    my_vec.push(one);
    my_vec.push(two);
}

但不幸的是,失败了,并出现以下错误

error[E0277]: the trait bound `SuperOne: AnySuper` is not satisfied
  --> src/main.rs:52:17
   |
52 |     my_vec.push(one);
   |                 ^^^ the trait `AnySuper` is not implemented for `SuperOne`
   |
   = note: required for the cast to the object type `dyn AnySuper`

error[E0277]: the trait bound `SuperTwo: AnySuper` is not satisfied
  --> src/main.rs:53:17
   |
53 |     my_vec.push(two);
   |                 ^^^ the trait `AnySuper` is not implemented for `SuperTwo`
   |
   = note: required for the cast to the object type `dyn AnySuper`

这有点奇怪,因为在我看来,我已经为所有人实现了AnySuperSuper

附言:我已经在https://play.rust-lang.org/?version=stable用这个代码建立了一个操场


共有1个答案

步兴为
2023-03-14

我认为有些奇怪的事情正在发生,因为你正在经历两层间接的特征对象,即从具体的< code >框

但是,从它的声音来看,您想说“每当Super适用于任何T时,AnySuper都会实现”,并且您在代码中写的是“AnySuper是为这个名为dyn Super的有趣特征对象类型实现的。

impl<S, T> AnySuper for S where S : Super<T>, T : Base

但现在我们收到了一些关于无约束类型的相当令人兴奋的错误消息。

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:36:9
   |
36 | impl<S, T> AnySuper for S where S : Super<T>, T : Base {
   |         ^ unconstrained type parameter

您可以在相关的RFC上阅读有关此错误动机的更多信息,但归根结底,Rust无法确定对于某些任意的S,t应该是什么。

总的来说,这是正确的。如果你给 Rust 一些任意的东西来实现 Super

trait Super {
    type T : Base;
    fn say_hi(&self) -> &'static str {
        Self::T::say_hi()
    }
}

impl Super for SuperOne {
    type T = BaseOne;
}
impl Super for SuperTwo {
    type T = BaseTwo;
}

impl<S> AnySuper for S where S : Super, S::T : Base {
    fn say_hi(&self) -> &'static str {
        Super::say_hi(self)
    }
}

现在 Rust 会很乐意接受 AnySuper 的向量。

Rust Playground链接

工作代码示例:

trait Base {
    fn say_hi() -> &'static str;
}

struct BaseOne {}
struct BaseTwo {}

impl Base for BaseOne {
    fn say_hi() -> &'static str {
        "hi!"
    }
}

impl Base for BaseTwo {
    fn say_hi() -> &'static str {
        "hello!"
    }
}

trait Super {
    type T : Base;
    fn say_hi(&self) -> &'static str {
        Self::T::say_hi()
    }
}

struct SuperOne;
struct SuperTwo;

impl Super for SuperOne {
    type T = BaseOne;
}
impl Super for SuperTwo {
    type T = BaseTwo;
}

trait AnySuper {
    fn say_hi(&self) -> &'static str;
}

impl<S> AnySuper for S where S : Super, S::T : Base {
    fn say_hi(&self) -> &'static str {
        Super::say_hi(self)
    }
}

fn main() {
    let one = Box::new(SuperOne);
    let two = Box::new(SuperTwo);
    
    let mut my_vec: Vec<Box<dyn AnySuper>> = Vec::new();
    
    my_vec.push(one);
    my_vec.push(two);
    
    println!("Success!");
}

 类似资料:
  • 我当前的Cucumber文件如下所示: 所以现在我想再添加几个场景,可能是在同一个文件中进行API测试。所以我想为此创建一个新特性,而不是使用Feature:Test Online application页面。这样我就不需要为API测试创建单独的特性文件。

  • (这是我第二次尝试追踪我的确切问题。查看编辑历史记录) 我有一个简单的通用特性和两种不同的实现: 我现在想要一个包含两个实现元素的向量。正如我在这里学到的,我做: 但是编译器不同意: 一方面,这是有道理的。另一方面,我应该为写什么?我希望它是通用的,所以我不能简单地在那里放或。我可以做

  • 将跟踪和跨度添加到Slf4J MDC,以便您可以从日志聚合器中的给定跟踪或跨度中提取所有日志。示例日志: 2016-02-02 15:30:57.902 INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ... 2016-02-02 15:30:58.372 ERROR [bar,6bfd

  • 反缓存 anticache设置该选项后,它将删除可能引起服务器响应的Header(if-none-match和if-modified-since)304 not modified。当您要确保完全捕获HTTP交换时,这很有用。当您要确保服务器以完整的数据响应时,也经常在客户端重播期间使用它。 客户端重播 客户端重播可以做到:您提供了一个以前保存的HTTP对话,而mitmproxy则一个接一个地重播了

  •   特征缩放是用来统一资料中的自变项或特征范围的方法,在资料处理中,通常会被使用在资料前处理这个步骤。 1 动机   因为在原始的资料中,各变数的范围大不相同。对于某些机器学习的算法,若没有做过标准化,目标函数会无法适当的运作。举例来说,多数的分类器利用两点间的距离计算两点的差异, 若其中一个特征具有非常广的范围,那两点间的差异就会被该特征左右,因此,所有的特征都该被标准化,这样才能大略的使各特征