无法找出一个函数来返回对存储在 RefCell> 中的给定类型的引用

2023-11-30

其中大部分是样板文件,作为可编译的示例提供。向下滚动。

use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::any::{Any, AnyRefExt};

struct Shared {
    example: int,
}

struct Widget {
    parent: Option<Weak<Box<Widget>>>,
    specific: RefCell<Box<Any>>,
    shared: RefCell<Shared>,
}

impl Widget {
    fn new(specific: Box<Any>, 
           parent: Option<Rc<Box<Widget>>>) -> Rc<Box<Widget>> { 
        let parent_option = match parent {
            Some(parent) => Some(parent.downgrade()),
            None => None,
        };
        let shared = Shared{pos: 10};
        Rc::new(box Widget{
            parent: parent_option,
            specific: RefCell::new(specific),
            shared: RefCell::new(shared)})
    }
}

struct Woo {
    foo: int,
}

impl Woo {
    fn new() -> Box<Any> {
        box Woo{foo: 10} as Box<Any>
    }
}

fn main() {
    let widget = Widget::new(Woo::new(), None);

    {
        // This is a lot of work...
        let cell_borrow = widget.specific.borrow();
        let woo = cell_borrow.downcast_ref::<Woo>().unwrap();
        println!("{}", woo.foo);
    }

    // Can the above be made into a function?
    // let woo = widget.get_specific::<Woo>();
}

我正在学习 Rust 并试图找出一些可行的方法来构建小部件层次结构。上面基本上就满足了我的需要,但是有点麻烦。尤其令人烦恼的是,我必须使用两个语句来转换内部小部件(specific成员Widget)。我尝试了几种方法来编写一个可以完成这一切的函数,但是参考的数量和生命周期的魔力超出了我的范围。

能做到吗?我的示例代码底部注释掉的方法可以实现吗?

对于有关完成整个事情的更好方法的评论表示赞赏,但请将其放在评论部分(或创建一个新问题并将其链接)


我将仅介绍您的代码的工作简化版和更惯用的版本,然后解释我在那里所做的所有更改:

use std::rc::{Rc, Weak};
use std::any::{Any, AnyRefExt};

struct Shared {
    example: int,
}

struct Widget {
    parent: Option<Weak<Widget>>,
    specific: Box<Any>,
    shared: Shared,
}

impl Widget {
    fn new(specific: Box<Any>, parent: Option<Rc<Widget>>) -> Widget { 
        let parent_option = match parent {
            Some(parent) => Some(parent.downgrade()),
            None => None,
        };
        let shared = Shared { example: 10 };
        Widget{
            parent: parent_option,
            specific: specific,
            shared: shared
        }
    }

    fn get_specific<T: 'static>(&self) -> Option<&T> {
        self.specific.downcast_ref::<T>()
    }
}

struct Woo {
    foo: int,
}

impl Woo {
    fn new() -> Woo {
        Woo { foo: 10 }
    }
}

fn main() {
    let widget = Widget::new(box Woo::new() as Box<Any>, None);

    let specific = widget.get_specific::<Woo>().unwrap();
    println!("{}", specific.foo);
}

首先,有一些不必要的RefCell位于您的结构内部。RefCell很少需要 - 仅当您需要仅使用来改变对象的内部状态时&参考(而不是&mut)。这是实现抽象的有用工具,但在应用程序代码中几乎不需要它。因为从你的代码中并不清楚你really需要它,我认为它被错误使用并且可以删除。

Next, Rc<Box<Something>> when Something是一个结构(就像你的情况一样Something = Widget)是多余的。将拥有的框放入引用计数框只是不必要的双重间接和分配。清楚的Rc<Widget>是表达这件事的正确方式。当动态大小的类型落地时,特征对象也是如此。

最后,您应该尝试始终返回未装箱的值。返回Rc<Box<Widget>>(甚至Rc<Widget>) 对于代码的调用者来说是不必要的限制。你可以从Widget to Rc<Widget>很容易,但反之则不然。 Rust 自动优化按值回报;如果您的来电者需要Rc<Widget>他们可以自己装箱返回值:

let rc_w = box(RC) Widget::new(...);

同样的事情也适用于Box<Any>由返回Woo::new().

你可以看到,在没有RefCells your get_specific()方法可以非常容易地实现。但是,你真的不能这样做RefCell因为RefCell使用 RAII 进行动态借用检查,因此您无法从方法返回对其内部的引用。你必须回来core::cell::Refs,并且您的呼叫者将需要downcast_ref()他们自己。这只是使用的另一个原因RefCell是有节制的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法找出一个函数来返回对存储在 RefCell> 中的给定类型的引用 的相关文章

随机推荐

  • OCaml“else”语法错误

    我是第一次学习 OCaml 我遇到了一个非常模糊的 语法错误 的麻烦 定义函数时generateboxes像这样 let rec generateboxes a b if a add1 b then force newline print
  • 两条弧线之间的交点? (弧 = 一对角之间的距离)

    我正在尝试找到一种方法来计算两条弧之间的交点 我需要用它来确定圆弧在视觉上有多少在右半边 有多少在左半边 我考虑创建右半部分的弧 并将其与实际弧相交 但我花了很多时间来解决这个问题 所以我想在这里问 以前肯定有人做过 编辑 很抱歉 当我在处
  • 如何在 C++ 中从二进制文件中删除部分

    我想使用 C 从二进制文件中删除部分 二进制文件大约有 5 10 MB 左右 我想做的事 搜索 ANSI 字符串 something 一旦找到这个字符串 我想删除接下来的n个字节 例如下面的1MB数据 我想删除这些字符 而不是用 NULL
  • Linq to XML(Base64 编码)

    我必须将 PDF 转换为 Base64 编码并将其写入 XML 文件中的元素 我已经得到了 Base64 编码的字符串 很长 很大 但我工作的规范如下 选择此选项是为了确保 XML 文件可以在没有任何潜在风险的情况下显示和验证 由于处理原始
  • 在 Gnome 或 KDE 中以编程方式在桌面上移动应用程序窗口

    我想使用 C 程序在桌面上重新定位应用程序窗口 我应该如何去做 我需要针对这两种情况的解决方案 当我拥有想要移动的应用程序的源时 通过编写外部程序来移动其他应用程序的窗口 外部 Bash 脚本 xdotool search onlyvisi
  • 如何使用c#使用Youtube api登录程序?

    有this文档 可用的 所以我用了 YouTubeRequestSettings settings new YouTubeRequestSettings Appname devkey textBox1 Text textBox2 Text
  • 使用 mkmap 加载地图时显示标题

    我可以在 iphone 应用程序项目中显示地图 并将图钉放置在我想要的位置 但我希望在视图加载时显示标题和副标题 这是我正在使用的代码 我以为放入 mapView selectAnnotation 注释动画 是 会起作用 但事实并非如此 有
  • 在调试时使用反汇编语言在什么情况下有用

    我有以下基本问题 何时我们应该在调试中涉及反汇编 如何解释反汇编 例如下面每个段代表什么 00637CE3 8B 55 08 mov edx dword ptr arItem 00637CE6 52 push edx 00637CE7 6A
  • 在 PHP 中如何清除 WSDL 缓存?

    在通过php info 保存 WSDL 缓存的位置 tmp 但我不一定知道删除所有以 WSDL 开头的文件是否安全 Yes I should能够删除所有内容 tmp 但我不知道如果我删除所有 WSDL 文件还会产生什么影响 您可以安全地删除
  • C# 根据变量的内容调用方法

    如何根据变量的内容调用方法 ex String S Hello World String Format ToUpper String sFormat s Format resulting in HELLO WORLD 这样我就可以在其他时间
  • 使用 Plink 执行 (sudo) 子命令

    我正在尝试从 Window PowerShell 命令 Linux 机器 这些命令取决于之前命令的失败 通过 因此 我必须将所有命令放在一起 我尝试了多种将命令组合在一起的方法 但最后我只收到第一个命令的输出 PS C Users sams
  • iOS 更新至 10.3.1 破坏了 HTML 输入元素

    我们有一个主要由 iPad 在现场使用的网站 不是一个应用程序 大小适合在 iPad 上使用 显然刚刚发布的更新导致了输入问题 我们有一个 HTML 输入 用于允许他们从保存的图片中进行选择
  • React VR 组件和本机模块代码之间的持久桥梁

    我试图让浏览器将一些 DOM 事件发送到 React VR 组件中 我得到的最接近的是使用 本机模块 的代码 客户端 js const windowEventsModule new WindowEventsModule function i
  • 为什么我的 GUI 看起来总是不正确?

    在 Mac 上使用 Java 中的 Netbeans GUI 构建器构建 Netbeans 中的 GUI 如下所示 当我点击预览时 看起来还不错 但有一些小变化 最后 当我运行它时 它看起来像这样 糟糕 我认为这与 Java 的 外观和感觉
  • Highcharts - 如何在日期时间 x 轴上居中标签?

    我很难弄清楚如何在 Highcharts 中的日期时间 x 轴上居中标签而不使用类别和 tickPlacement 因为 tickPlacement 仅适用于类别 我的轴是动态创建的 因此我不能简单地设置 x 偏移或填充 因为这会导致不同间
  • bv-enable-int2bv-传播选项

    set option bv enable int2bv propagation true 在线工作 但是 我的本地版本对此有所抱怨 说 错误 第 1 行第 43 列 未知参数 bv enable int2bv propagation 这是一
  • Firebase 身份验证自定义声明不会传播到客户端

    我有一个 UID 1 的用户 其中自定义声明设置为 frompos true 我通过以下方式从 ADMIN SDK for java 向该用户设置新的自定义声明 Map
  • Neo4j如何避免超级节点

    在我的 Neo4j 项目中我有Role and Permission代表用户角色和权限的实体 每个User系统中的内容与适当的角色和权限集有关系 I think Role and Permission是某种超级节点 从性能的角度来看 它们将
  • android循环出现问题-无法将值放入hashmap

    这个问题困扰了我很长时间 我使用了一个叫bmob的云数据库 我发现我可以成功获取我想要的数据 但是 循环中可能会出现一些错误 我只能获取最后选择的项目的信息 附注我使用一个名为 Playlist 的数组列表来存储计算数据 我将使用该数据在下
  • 无法找出一个函数来返回对存储在 RefCell> 中的给定类型的引用

    其中大部分是样板文件 作为可编译的示例提供 向下滚动 use std rc Rc Weak use std cell RefCell use std any Any AnyRefExt struct Shared example int s