首页 > 其他分享 >Rust的ToOwned特征:泛型版的Clone

Rust的ToOwned特征:泛型版的Clone

时间:2024-02-28 12:45:10浏览次数:21  
标签:ToOwned String Clone fn str 泛型 self Rust

std::borrow::ToOwned是Rust标准库中的一个特征,用于从借用的数据中创建一个具有所有权的副本。它的作用和Clone是一样的,但是相比Clone,它支持泛型;也就是说我们可以将一个类型T“Clone”为另一个类型U。这对处理一些特殊的类型来说很有用。

ToOwned的签名

ToOwned提供了两个方法,其中一个是必须实现的:

pub trait ToOwned {
    type Owned: Borrow<Self>;

    // Required method
    fn to_owned(&self) -> Self::Owned;

    // Provided method
    fn clone_into(&self, target: &mut Self::Owned) { ... }
}

例子

说到例子,就不得不再次请出我文章里的常客——str[T]。众所周知,因为str[T]是切片类型,它们在编译时大小未知,因此Rust无法在栈上为它们分配空间;这就导致了我们几乎不会直接持有str[T]变量:

fn main() {
    let foo: str;
    let bar: [i32];
}

这段代码会被编译器直接报错:

str[T]是不能被持有了,但是Clone它们的需求是确实存在的;因此,Rust就提供了将这些切片类型“Clone”为栈上类型的方案:ToOwned。打开标准库文档和源码,我们可以看到str这样实现了ToOwned

#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for str {
    type Owned = String;
    #[inline]
    fn to_owned(&self) -> String {
        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
    }

    fn clone_into(&self, target: &mut String) {
        let mut b = mem::take(target).into_bytes();
        self.as_bytes().clone_into(&mut b);
        *target = unsafe { String::from_utf8_unchecked(b) }
    }
}

也可以看到[T]这样实现了ToOwned

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> ToOwned for [T] {
    type Owned = Vec<T>;
    #[cfg(not(test))]
    fn to_owned(&self) -> Vec<T> {
        self.to_vec()
    }

    #[cfg(test)]
    fn to_owned(&self) -> Vec<T> {
        hack::to_vec(self, Global)
    }

    fn clone_into(&self, target: &mut Vec<T>) {
        SpecCloneIntoVec::clone_into(self, target);
    }
}

于是,用户虽然不能直接Clonestr[T],但却可以把它们用ToOwned“Clone”为StringVec<T>


小插曲:在日常开发中,我们经常使用的方法String::from(&str),其实现正是依赖于strto_owned特征:

#[stable(feature = "rust1", since = "1.0.0")]
impl From<&str> for String {
    #[inline]
    fn from(s: &str) -> String {
        s.to_owned()
    }
}

总结

对普通的开发者来说,对ToOwned有一些了解就已经完全足够了;而对API的设计者来说,巧用ToOwned可以让你的类型在一些特殊情况下更灵活、更高效。


下篇文章介绍的是Rust中经常被人忽视的智能指针Cow,我之前在学习Rust时就注意到无论是the book,还是Rust圣经,都没有讲到Cow,希望我的工作能为Rust增加一点可供新人参考的资料。

标签:ToOwned,String,Clone,fn,str,泛型,self,Rust
From: https://www.cnblogs.com/cinea/p/18039926

相关文章

  • gogs修改gitclone 仓库地址
      查看gogsdocker容器的名称dockerps进入容器内部dockerexec-itd1bba9f39a02/bin/bash编辑gogs容器的配置文件 vi/data/gogs/conf/app.ini  [server]DOMAIN= gogs.ceshi.online   #这个是ssh的地址  HTTP_PORT=3000EXTERNAL_......
  • 泛型
    泛型的理解和好处看一个需求请编写程序,在ArrayList中,添加3个Dog对象Dog对象含有name和age,并输出name和age(要求使用getXxx0)先使用传统的方法来解决->引出泛型classDog{publicStringname;publicintage;publicDog(Stringname,intage){......
  • 泛型
     1.介绍泛型(Generics):是Java语言中一项重要特性,允许在类、接口和方法中使用参数化类型。通过泛型,可以编程通用、灵活的代码。提高代码的重用性和类型安全性。泛型是JavaSE1.5的新特性,是一种不确定的数据类型,这种不确定的数据类型需要我们在使用这个类的时候它才能够......
  • dremio cloner 简单试用
    以前简单介绍过dremiocloner工具,以下是一个简单试用dremio环境准备基于docker-compose,具体可以参考https://github.com/rongfengliang/dremio_cluster_docker-compose完成配置安装dremioclonerdremiocloner没有直接提供为一个pip包,需要自己安装clone代码......
  • ts泛型08
    泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性 //需求:定义一个函数,传入两个参数,第一个参数是数据,第二个参数是数量,//函数的作用:根据数量产生对应个数的数据,存放在一个数组中functionGetaArr<T>(value:T,count:......
  • Flink 使用之 TypeInformation 由于泛型类型在运行时会被JVM擦除,所以要指定类型
    Flink使用之TypeInformation由于泛型类型在运行时会被JVM擦除,所以要指定类型Flink使用介绍相关文档目录Flink使用介绍相关文档目录背景本篇从近期遇到的StreamJavaAPI问题,引出TypeInformation的使用。Exceptioninthread"main"org.apache.flink.api.common.functi......
  • JAVA基础-泛型
    1,泛型概述泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型......
  • Java之泛型系列--继承父类与实现多个接口(有示例)
    原文网址:​​Java之泛型系列--继承父类与实现多个接口(有示例)_IT利刃出鞘的博客-CSDN博客​​简介本文介绍java如何用泛型表示继承父类并实现多个接口。用泛型表示某个类是某个类的子类或者实现了接口的方法为:<TextendsA&B&C> 用法1:全都是接口。对于本例来说:A、B......
  • C# 泛型方法New泛型对象
     var frm=Activator.CreateInstance<T>(); ///<summary>//////</summary>///<typeparamname="T"></typeparam>///<paramname="pnlFrm"></param>///......
  • openWrt使用rclone挂载webDav
    前言觉得路由器(linux)硬盘太小,又不好扩展(x86机器可以插硬盘、但arm机器的硬盘是焊死的无法扩展)。这个时候,我们可以通过davfs或者rclone将外部资源如webDav挂载到本机上用来作为自己的硬盘。安装rclone#新版的rclone依赖fuse3,所系需要安装(尽管rclone的子依赖包含fuse但那是旧版......