当前位置: 首页 > news >正文

网站建设需要资质么网站续费模板

网站建设需要资质么,网站续费模板,wordpress 文章列表页,中国电子商务研究中心文章目录 6 方法 Method6.1 定义方法self、self 和 mut self 6.2 自动引用和解引用6.3 关联函数 7 泛型和特征7.1 泛型 Generics7.1.1 结构体中使用泛型7.1.2 枚举中使用泛型7.1.3 方法中使用泛型为具体的泛型类型实现方法 7.1.4 const 泛型 7.2 特征 Trait7.2.1 为类… 文章目录 6 方法 Method6.1 定义方法self、self 和 mut self 6.2 自动引用和解引用6.3 关联函数 7 泛型和特征7.1 泛型 Generics7.1.1 结构体中使用泛型7.1.2 枚举中使用泛型7.1.3 方法中使用泛型为具体的泛型类型实现方法 7.1.4 const 泛型 7.2 特征 Trait7.2.1 为类型实现特征7.2.2 使用特征作为函数参数7.2.3 特征约束(trait bound)多重约束where约束 7.2.4 函数返回中的impl trait7.2.5 两个综合例子为自定义类型实现 操作自定义类型的打印输出 7.3 特征对象 6 方法 Method Rust中方法往往和对象成对出现object.method()。Rust 的方法往往跟结构体、枚举、特征(Trait)一起使用 6.1 定义方法 Rust 使用 impl 来定义方法例如以下代码 struct Circle {x: f64,y: f64,radius: f64, }impl Circle {// new是Circle的关联函数因为它的第一个参数不是self且new并不是关键字// 这种方法往往用于初始化当前结构体的实例fn new(x: f64, y: f64, radius: f64) - Circle {Circle {x: x,y: y,radius: radius,}}// Circle的方法self表示借用当前的Circle结构体fn area(self) - f64 {std::f64::consts::PI * (self.radius * self.radius)} }注Rust 的对象定义和方法定义是分离的这种数据和使用分离的方式会给予使用者极高的灵活度。 self、self 和 mut self 在一个 impl 块内Self 指代被实现方法的结构体类型self 指代此类型的实例即为哪个结构体实现方法那么 self 就是指代哪个结构体的实例。self 依然有所有权的概念 self 表示 Rectangle 的所有权转移到该方法中这种形式用的较少self 表示该方法对 Rectangle 的不可变借用mut self 表示可变借用 self 的使用就跟函数参数一样要严格遵守 Rust 的所有权规则。使用方法代替函数有以下好处 不用在函数签名中重复书写 self 对应的类型代码的组织性和内聚性更强对于代码维护和阅读来说好处巨大 在 Rust 中允许方法名跟结构体的字段名相同往往适用于实现 getter 访问器 pub struct Rectangle {width: u32,height: u32, }impl Rectangle {pub fn new(width: u32, height: u32) - Self {Rectangle { width, height }}pub fn width(self) - u32 {return self.width;} }fn main() {let rect1 Rectangle::new(30, 50);println!({}, rect1.width()); }用这种方式我们可以把 Rectangle 的字段设置为私有属性只需把它的 new 和 width 方法设置为公开可见那么用户就可以创建一个矩形同时通过访问器 rect1.width() 方法来获取矩形的宽度因为 width 字段是私有的当用户访问 rect1.width 字段时就会报错。注意在此例中Self 指代的就是被实现方法的结构体 Rectangle。 6.2 自动引用和解引用 在 C/C 语言中有两个不同的运算符来调用方法. 直接在对象上调用方法而 - 在一个对象的指针上调用方法这时需要先解引用指针。换句话说如果 object 是一个指针那么 object-something() 和 (*object).something() 是一样的。 Rust 并没有一个与 - 等效的运算符相反Rust 有一个叫 自动引用和解引用的功能。方法调用是 Rust 中少数几个拥有这种行为的地方。他是这样工作的当使用 object.something() 调用方法时Rust 会自动为 object 添加 、mut 或 * 以便使 object 与方法签名匹配。也就是说这些代码是等价的: p1.distance(p2); (p1).distance(p2);第一行看起来简洁的多。这种自动引用的行为之所以有效是因为方法有一个明确的接收者———— self 的类型。在给出接收者和方法名的前提下Rust 可以明确地计算出方法是仅仅读取self做出修改mut self或者是获取所有权self。事实上Rust 对方法接收者的隐式借用让所有权在实践中更友好。 6.3 关联函数 思考一个问题如何为一个结构体定义一个构造器方法也就是接受几个参数然后构造并返回该结构体的实例。其实答案在开头的代码片段中就给出了很简单参数中不包含 self 即可。 这种定义在 impl 中且没有 self 的函数被称之为关联函数 因为它没有 self不能用 f.read() 的形式调用因此它是一个函数而不是方法它又在 impl 中与结构体紧密关联因此称为关联函数。 在之前的代码中我们已经多次使用过关联函数例如 String::from用于创建一个动态字符串。 impl Rectangle {fn new(w: u32, h: u32) - Rectangle {Rectangle { width: w, height: h }} }Rust 中有一个约定俗成的规则使用 new 来作为构造器的名称出于设计上的考虑Rust 特地没有用 new 作为关键字 因为是函数所以不能用 . 的方式来调用我们需要用 :: 来调用例如 let sq Rectangle::new(3, 3);。这个方法位于结构体的命名空间中:: 语法用于关联函数和模块创建的命名空间。 Rust 允许我们为一个结构体定义多个 impl 块目的是提供更多的灵活性和代码组织性例如当方法多了后可以把相关的方法组织在同一个 impl 块中那么就可以形成多个 impl 块各自完成一块儿目标。 除了结构体还可以为枚举、特征(trait)实现方法如 #![allow(unused)] enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32), }impl Message {fn call(self) {// 在这里定义方法体} }fn main() {let m Message::Write(String::from(hello));m.call(); }7 泛型和特征 7.1 泛型 Generics 使用泛型参数有一个先决条件必需在使用前对其进行声明 fn largestT(list: [T]) - T {}可以这样理解这个函数定义函数 largest 有泛型类型 T它有个参数 list其类型是元素为 T 的数组切片最后该函数返回值的类型也是 T。 7.1.1 结构体中使用泛型 结构体中的字段类型也可以用泛型来定义下面代码定义了一个坐标点 Point它可以存放任何类型的坐标值 struct PointT {x: T,y: T, }fn main() {let integer Point { x: 5, y: 10 };let float Point { x: 1.0, y: 4.0 }; }这里有两点需要特别的注意 提前声明跟泛型函数定义类似首先我们在使用泛型参数之前必需要进行声明 PointT接着就可以在结构体的字段类型中使用 T 来替代具体的类型x 和 y 是相同的类型若需要不同类型将声明改为struct PointT,U { x: T, y: U, } 7.1.2 枚举中使用泛型 Option 枚举类型 enum OptionT {Some(T),None, }OptionT 是一个拥有泛型 T 的枚举类型它第一个成员是 Some(T)存放了一个类型为 T 的值。可以在任何一个需要返回值的函数中去使用 OptionT 枚举类型来做为返回值用于返回一个任意类型的值 Some(T)或者没有值 None。 Result枚举类型 enum ResultT, E {Ok(T),Err(E), }主要用于函数返回值如果函数正常运行则最后返回一个 Ok(T)T 是函数具体的返回值类型如果函数异常运行则返回一个 Err(E)E 是错误类型。例如打开一个文件如果成功打开文件则返回 Ok(std::fs::File)因此 T 对应的是 std::fs::File 类型而当打开文件时出现问题时返回 Err(std::io::Error)E 对应的就是 std::io::Error 类型。 7.1.3 方法中使用泛型 在结构体的方法中定义额外的泛型参数就跟泛型函数一样 struct PointT, U {x: T,y: U, }implT, U PointT, U {fn mixupV, W(self, other: PointV, W) - PointT, W {Point {x: self.x,y: other.y,}} }fn main() {let p1 Point { x: 5, y: 10.4 };let p2 Point { x: Hello, y: c};let p3 p1.mixup(p2);println!(p3.x {}, p3.y {}, p3.x, p3.y); }这个例子中T,U 是定义在结构体 Point 上的泛型参数V,W 是单独定义在方法 mixup 上的泛型参数可以理解为一个是结构体泛型一个是函数泛型。 为具体的泛型类型实现方法 对于 PointT 类型你不仅能定义基于 T 的方法还能针对特定的具体类型进行方法定义 impl Pointf32 {fn distance_from_origin(self) - f32 {(self.x.powi(2) self.y.powi(2)).sqrt()} }这段代码意味着 Pointf32 类型会有一个方法 distance_from_origin而其他 T 不是 f32 类型的 PointT 实例则没有定义此方法。这个方法计算点实例与坐标(0.0, 0.0) 之间的距离并使用了只能用于浮点型的数学运算符。 这样我们就能针对特定的泛型类型实现某个特定的方法对于其它泛型类型则没有定义该方法 7.1.4 const 泛型 const 泛型针对值的泛型可以用于处理数组长度的问题 fn display_arrayT: std::fmt::Debug, const N: usize(arr: [T; N]) {println!({:?}, arr); } fn main() {let arr: [i32; 3] [1, 2, 3];display_array(arr);let arr: [i32; 2] [1, 2];display_array(arr); }如上所示我们定义了一个类型为 [T; N] 的数组其中 T 是一个基于类型的泛型参数重点在于 N 这个泛型参数它是一个基于值的泛型参数因为它用来替代的是数组的长度。 注意的是需要对 T 加一个限制 std::fmt::Debug该限制表明 T 可以用在 println!({:?}, arr) 中因为 {:?} 形式的格式化输出需要 arr 实现该特征。 N 就是 const 泛型定义的语法是 const N: usize表示 const 泛型 N 它基于的值类型是 usize。 Rust 通过在编译时进行泛型代码的 单态化(monomorphization)来保证效率。单态化是一个通过填充编译时使用的具体类型将通用代码转换为特定代码的过程。 编译器所做的工作正好与我们创建泛型函数的步骤相反编译器寻找所有泛型代码被调用的位置并针对具体类型生成代码。 7.2 特征 Trait 特征类似于其他语言中的接口定义了一组可以被共享的行为只要实现了特征你就能使用这组行为。 7.2.1 为类型实现特征 因为特征只定义行为看起来是什么样的因此我们需要为类型实现具体的特征定义行为具体是怎么样的。 首先来为 Post 和 Weibo 实现 Summary 特征 //特征定义也可以在特征中定义具有默认实现的方法 pub trait Summary {fn summarize(self) - String; }pub struct Post {pub title: String, // 标题pub author: String, // 作者pub content: String, // 内容 } //特征实现 impl Summary for Post {fn summarize(self) - String {format!(文章{}, 作者是{}, self.title, self.author)} }pub struct Weibo {pub username: String,pub content: String }impl Summary for Weibo {fn summarize(self) - String {format!({}发表了微博{}, self.username, self.content)} }实现特征的语法与为结构体、枚举实现方法很像impl Summary for Post读作“为 Post 类型实现 Summary 特征”然后在 impl 的花括号中实现该特征的具体方法。 关于特征实现与定义的位置有一条非常重要的原则如果你想要为类型 A 实现特征 T那么 A 或者 T 至少有一个是在当前作用域中定义的 7.2.2 使用特征作为函数参数 定义一个函数使用特征作为函数参数 pub fn notify(item: impl Summary) {println!(Breaking news! {}, item.summarize()); }impl Summary它的意思是 实现了Summary特征 的 item 参数。 你可以使用任何实现了 Summary 特征的类型作为该函数的参数同时在函数体内还可以调用该特征的方法例如 summarize 方法。具体的说可以传递 Post 或 Weibo 的实例来作为参数而其它类如 String 或者 i32 的类型则不能用做该函数的参数因为它们没有实现 Summary 特征。 7.2.3 特征约束(trait bound) 虽然 impl Trait 这种语法非常好理解但是实际上它只是一个语法糖 pub fn notifyT: Summary(item: T) {println!(Breaking news! {}, item.summarize()); }真正的完整书写形式如上所述形如 T: Summary 被称为特征约束。 在简单的场景下 impl Trait 这种语法糖就足够使用但是对于复杂的场景特征约束可以让我们拥有更大的灵活性和语法表现能力例如一个函数接受两个 impl Summary 的参数 pub fn notify(item1: impl Summary, item2: impl Summary) {}如果函数两个参数是不同的类型那么上面的方法很好只要这两个类型都实现了 Summary 特征即可。但是如果我们想要强制函数的两个参数是同一类型呢上面的语法就无法做到这种限制此时我们只能使特征约束来实现 pub fn notifyT: Summary(item1: T, item2: T) {}泛型类型 T 说明了 item1 和 item2 必须拥有同样的类型同时 T: Summary 说明了 T 必须实现 Summary 特征。 多重约束 pub fn notifyT: Summary Display(item: T) {}通过这两个特征就可以使用 item.summarize 方法以及通过 println!({}, item) 来格式化输出 item。 where约束 当特征约束变得很多时函数的签名将变得很复杂 fn some_functionT: Display Clone, U: Clone Debug(t: T, u: U) - i32 {}严格来说上面的例子还是不够复杂但是我们还是能对其做一些形式上的改进通过 where fn some_functionT, U(t: T, u: U) - i32where T: Display Clone,U: Clone Debug {}7.2.4 函数返回中的impl trait 可以通过 impl Trait 来说明一个函数返回了一个类型该类型实现了某个特征 fn returns_summarizable() - impl Summary {Weibo {username: String::from(sunface),content: String::from(m1 max太厉害了电脑再也不会卡,)} }因为 Weibo 实现了 Summary因此这里可以用它来作为返回值。要注意的是虽然我们知道这里是一个 Weibo 类型但是对于 returns_summarizable 的调用者而言他只知道返回了一个实现了 Summary 特征的对象但是并不知道返回了一个 Weibo 类型。 当函数返回的真实类型非常复杂不知道该怎么声明时(毕竟 Rust 要求你必须标出所有的类型)此时就可以用 impl Trait 的方式简单返回。例如闭包和迭代器就是很复杂只有编译器才知道那玩意的真实类型如果让你写出来它们的具体类型估计内心有一万只草泥马奔腾好在你可以用 impl Iterator 来告诉调用者返回了一个迭代器因为所有迭代器都会实现 Iterator 特征。 7.2.5 两个综合例子 为自定义类型实现 操作 在 Rust 中除了数值类型的加法String 也可以做加法因为 Rust 为该类型实现了 std::ops::Add 特征同理如果我们为自定义类型实现了该特征那就可以自己实现 Point1 Point2 的操作: use std::ops::Add;// 为Point结构体派生Debug特征用于格式化输出 #[derive(Debug)] struct PointT: AddT, Output T { //限制类型T必须实现了Add特征否则无法进行操作。x: T,y: T, }implT: AddT, Output T Add for PointT {type Output PointT;fn add(self, p: PointT) - PointT {Point{x: self.x p.x,y: self.y p.y,}} }fn addT: AddT, OutputT(a:T, b:T) - T {a b }fn main() {let p1 Point{x: 1.1f32, y: 1.1f32};let p2 Point{x: 2.1f32, y: 2.1f32};println!({:?}, add(p1, p2));let p3 Point{x: 1i32, y: 1i32};let p4 Point{x: 2i32, y: 2i32};println!({:?}, add(p3, p4)); }自定义类型的打印输出 在开发过程中往往只要使用 #[derive(Debug)] 对我们的自定义类型进行标注即可实现打印输出的功能 #[derive(Debug)] struct Point{x: i32,y: i32 } fn main() {let p Point{x:3,y:3};println!({:?},p); }但是在实际项目中往往需要对我们的自定义类型进行自定义的格式化输出以让用户更好的阅读理解我们的类型此时就要为自定义类型实现 std::fmt::Display 特征 #![allow(dead_code)]use std::fmt; use std::fmt::{Display};#[derive(Debug,PartialEq)] enum FileState {Open,Closed, }#[derive(Debug)] struct File {name: String,data: Vecu8,state: FileState, }impl Display for FileState {fn fmt(self, f: mut fmt::Formatter) - fmt::Result {match *self {FileState::Open write!(f, OPEN),FileState::Closed write!(f, CLOSED),}} }impl Display for File {fn fmt(self, f: mut fmt::Formatter) - fmt::Result {write!(f, {} ({}),self.name, self.state)} }impl File {fn new(name: str) - File {File {name: String::from(name),data: Vec::new(),state: FileState::Closed,}} }fn main() {let f6 File::new(f6.txt);//...println!({:?}, f6);println!({}, f6); }7.3 特征对象 可以通过 引用或者 BoxT 智能指针的方式来创建特征对象。 trait Draw {fn draw(self) - String; }impl Draw for u8 {fn draw(self) - String {format!(u8: {}, *self)} }impl Draw for f64 {fn draw(self) - String {format!(f64: {}, *self)} }// 若 T 实现了 Draw 特征 则调用该函数时传入的 BoxT 可以被隐式转换成函数参数签名中的 Boxdyn Draw fn draw1(x: Boxdyn Draw) {// 由于实现了 Deref 特征Box 智能指针会自动解引用为它所包裹的值然后调用该值对应的类型上定义的 draw 方法x.draw(); }fn draw2(x: dyn Draw) {x.draw(); }fn main() {let x 1.1f64;// do_something(x);let y 8u8;// x 和 y 的类型 T 都实现了 Draw 特征因为 BoxT 可以在函数调用时隐式地被转换为特征对象 Boxdyn Draw // 基于 x 的值创建一个 Boxf64 类型的智能指针指针指向的数据被放置在了堆上draw1(Box::new(x));// 基于 y 的值创建一个 Boxu8 类型的智能指针draw1(Box::new(y));draw2(x);draw2(y); }上面代码有几个非常重要的点 draw1 函数的参数是 Boxdyn Draw 形式的特征对象该特征对象是通过 Box::new(x) 的方式创建的draw2 函数的参数是 dyn Draw 形式的特征对象该特征对象是通过 x 的方式创建的dyn 关键字只用在特征对象的类型声明上在创建时无需使用 dyn 因此可以使用特征对象来代表泛型或具体的类型。 泛型是在编译期完成处理的编译器会为每一个泛型参数对应的具体类型生成一份代码这种方式是静态分发(static dispatch)因为是在编译期完成的对于运行期性能完全没有任何影响。 与静态分发相对应的是动态分发(dynamic dispatch)在这种情况下直到运行时才能确定需要调用什么方法。之前代码中的关键字 dyn 正是在强调这一“动态”的特点。当使用特征对象时Rust 必须使用动态分发。 特征对象特点 特征对象大小不固定对于不同的类型可以实现相同特征几乎总是使用特征对象的引用方式如 dyn Draw、Boxdyn Draw引用大小是固定的占用两个指针大小ptr-指向实现了特征的具体类型的实例/vptr-指向虚表vtable 在Rust中一般Self代表类型self指代当前实例对象。 不是所有特征都能拥有特征对象只有对象安全的特征才行。当一个特征的所有方法都有如下属性时它的对象才是安全的 方法的返回类型不能是 Self方法没有任何泛型参数
http://www.w-s-a.com/news/538200/

相关文章:

  • 赛罕区城乡建设局网站什么是新媒体运营
  • 松原企业网站建设设计素材网排名
  • 网站建设是那个行业广东公司排名
  • 制作网站要多少钱seo是如何优化
  • 求个网站2020急急急做金融网站拘留多久
  • 网站后台管理系统怎么进seo网络推广外包公司
  • 中山市 做网站网站建设如何上传文件
  • 网站呢建设公众号制作要求
  • 网站备案证明在自己电脑上做网站
  • 沈阳旅游团购网站建设怎么制作网站搜索窗口
  • 做化学合成的网站有哪些枣庄住房和城乡建设局网站
  • 天猫优惠券网站怎么做的网络连接
  • 保定网站建设多少钱公司网页网站建设+ppt模板下载
  • 用户上传商品网站用什么做建设跳转公积金网站
  • 买程序的网站上海市网站建设公司
  • 南通网站建设排名公司哪家好wordpress网站图片迁移
  • 河南省汝州文明建设门户网站博客网站建设源码
  • 单位建设网站的请示手机移动端网站案例
  • 国内做网站的企业网站结构有哪些类型
  • 南通网站建设制作公司苏州好的网站公司名称
  • 咸阳做网站开发公司哪家好珠海公司制作网站
  • 深圳网站建设好不好医疗网站前置审批
  • 做ic什么网站好安溪网站建设
  • 网站建设 慕课企业文化标语经典
  • 做短视频的网站都有哪些简约 时尚 高端 网站建设
  • 浦口区网站建设售后服务建设一个网站多少钱
  • 做个小网站大概多少钱广州h5网站
  • 360免费建站视频wordpress标签显示图片
  • 创建简易个人网站国外做网站被动收入
  • 轻定制网站建设网页培训哪个机构好