【问题标题】:Using impl Trait inside another type that supports generics在另一种支持泛型的类型中使用 impl Trait
【发布时间】:2020-08-01 13:30:32
【问题描述】:

我有以下公共特征

pub trait UIElement {
    /// Is this UIElement a child of any other UIElement?
    fn parent<T: UIElement>(&self) -> Option<T>;

    /// Where to position
    /// TODO: Determine recursivly by checking the position of
    /// its parents.
    fn area(&self) -> Area;

    /// Should this UIElement be visible?
    fn visible(&self) -> bool;

    /// Is this UIElement actually visible?
    /// A UIElement can only be visible, if the parent (e.g. a container)
    /// is also visible (and its parent and so on resursively).
    fn actually_visible(&self) -> bool {
        let parent_visible: bool = if let Some(parent) = self.parent() {
            parent.actually_visible()
        }else { true };

        parent_visible && self.visible()
    }
}

actually_visible() 应该只返回 true,如果它本身是 visible() 并且之前的父级是 actually_visible() 递归的。

当我创建parent() 方法时,我不能只使用Option&lt;impl UIElement&gt;Option&lt;Self&gt;(如果我没记错的话,Self 可能只适用于实际结构)作为返回类型。然而,我选择的语法基本上应该是 Option&lt;impl UIElement&gt; 的无糖版本。
使用它,编译器至少不再抱怨了。 (虽然我还是有点恼火,但这不是这个问题的重点)。

现在问题在于actually_visible()
在尝试从中解析 actually_visible() 时,它无法推断父级的类型。

error[E0282]: type annotations needed
error[E0282]: type annotations needed
  --> src/ui.rs:40:13
   |
40 |             parent.actually_visible()
   |             ^^^^^^ cannot infer type
   |
   = note: type must be known at this point
help: consider specifying the type argument in the method call
   |
39 |         let parent_visible: bool = if let Some(parent) = self.parent::<T>() {
   |                                                                     ^^^^^

我怎样才能做到这一点?

P.S.:我已经研究了其他一些解决方案。虽然Is there a way to signal that an impl trait type also implements additional traits? 有一个非常相似的问题,但这似乎对我不起作用。也许 rust 编译器存在递归问题/限制?

【问题讨论】:

    标签: rust


    【解决方案1】:

    看起来您尝试使用泛型的唯一地方就是这一行:

    fn parent<T: UIElement>(&self) -> Option<T>;
    

    这不是必需的,因为 Rust 已经知道正在操作的实际类型将是实现 UIElement 的更具体的类型,因此这里似乎不需要使用泛型。

    话虽如此,因为 Rust 不提前知道将使用的实际对象的大小(因为它可能会有所不同),所以您需要依靠堆来保存这些对象。

    因此,我将返回类型中的T替换为

    Box<dyn UIElement>
    

    像这样……

    fn parent(&self) -> Option<Box<dyn UIElement>>;
    

    区域添加定义后

    pub struct Area
    {
    
    }
    

    我能够编译您的代码(尽管您用于“区域”的内容取决于您)。

    【讨论】:

    • Turbofish 已移除
    猜你喜欢
    • 2020-08-21
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2021-10-31
    • 2015-08-07
    • 1970-01-01
    相关资源
    最近更新 更多