写点什么

Rust 从 0 到 1- 结构体 - 一个例子

用户头像
关注
发布于: 2021 年 04 月 08 日
Rust从0到1-结构体-一个例子

为了理解在什么场景下使用结构体,下面将编写一个计算矩形面积的程序,从使用单独的变量开始,接着使用结构体对程序进行重构。

使用 Cargo 新建一个叫做 rectangles 的项目。它使用以像素为单位的宽度和高度进行矩形面积的计算。我们先来看看使用单独的变量的例子:

fn main() {    let width1 = 30;    let height1 = 50;    println!(        "The area of the rectangle is {} square pixels.",        area(width1, height1)    );}
fn area(width: u32, height: u32) -> u32 { width * height}
复制代码

虽然上面的例子可以运行,调用 area 函数并传入宽度和高度参数来计算出矩形的面积。其中宽度和高度是相关联的,因为一个矩形必然有这两个属性。同时函数 fn area(width: u32, height: u32) -> u32 的含义应该是计算矩形的面积,不是计算宽度和高度的乘积。因此将宽度和高度组合在一起将更易懂也更易处理。 元组类型似乎可以做到这一点,下面我们先使用元组对代码进行重构。

使用元组重构

使用元组对代码进行重构:

fn main() {    let rect1 = (30, 50);    println!(        "The area of the rectangle is {} square pixels.",        area(rect1)    );}
fn area(dimensions: (u32, u32)) -> u32 { dimensions.0 * dimensions.1}
复制代码

一方面元组帮助我们增加了一些结构性,并且现在只需传入一个参数;另一方面,元组并没有给出元素的名称,所以计算部分的代码不是那么易读易懂,在计算面积时将宽度和高度弄混倒没关系,但是,如果要在屏幕上绘制矩形,宽度和高度搞错了,绘制出来的图形是完全不一样的!因此,我们必须要知道并记住 width 的元组索引是 0,height 的元组索引是 1。如果别人要使用这些代码,我想他们可能需要注释的帮助,并在使用时牢记索引的含义,一点也不友好。下面我们再来试试结构体。

使用结构体重构

可以使用结构体为数据命名来,这样数据看起来就有含义了,而不仅仅是个数字:

struct Rectangle {  width: u32,  height: u32}
fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!( "The area of the rectangle is {} square pixels.", area(&rect1) );}
fn area(rectangle: &Rectangle) -> u32 { rectangle.width * rectangle.height}
复制代码

上面的例子中定义了一个结构体类型 Rectangle,并且在 area 函数中使用 Rectangle 的 width 和 height 字段计算 Rectangle 的面积,清晰明了(不需要再记住 0 和 1 的含义)。另外,我们使用了结构体的引用而不是获取它的所有权,这样 main 函数就可以保持 rect1 的所有权并继续使用它。

通过 trait 增加功能

我们在调试程序时可能会想打印出 Rectangle 实例来查看其字段的值,但是 println! 宏无法直接打印 Rectangle 类型,println! 宏能处理很多类型的格式,不过需要类型实现了 Display (std::fmt::Display),目前为止见过的基本类型都默认实现了 Display,不过对于结构体,由于其是用户自定义的类型,输出的格式是不明确的,所以结构体并没有提供一个 Display 实现。Rust 为我们提供了很多可以通过 derive 注解来使用的 trait,他们可以为我们的自定义类型增加实用的功能,在这先给出使用 derive 的例子,后面详细介绍 trait 用法:

#[derive(Debug)]      //增加 derive 注解struct Rectangle {  width: u32,  height: u32}
fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!( "The area of the rectangle is {} square pixels.", area(&rect1) );}
fn area(rectangle: &Rectangle) -> u32 { println!("rectangle is {:?}", rectangle); //将 {} 替换为 {:?} rectangle.width * rectangle.height}
复制代码

area 函数是比较特殊的,它只计算矩形的面积。那么如果这个行为与 Rectangle 结构体再结合得更紧密一些就更好了,就像 Java 中类的方法,因为它不能用于其他类型。那么在 Rust 中应该怎么做呢,下一个章节将进行介绍。

发布于: 2021 年 04 月 08 日阅读数: 9
用户头像

关注

公众号"山 顽石"欢迎大家关注;) 2021.03.23 加入

IT老兵,关注Rust、Java、前端、架构、大数据、AI、算法等;平时喜欢美食、旅游、宠物、健身、篮球、乒乓球等。希望能和大家交流分享。

评论

发布
暂无评论
Rust从0到1-结构体-一个例子