【发布时间】:2018-07-22 05:27:45
【问题描述】:
结构和枚举彼此相似。
什么时候使用结构体比使用枚举更好(反之亦然)?有人可以举一个明确的例子,说明使用结构比使用枚举更可取吗?
【问题讨论】:
-
另一个小细节:
pub enum公开所有细节(变体及其字段),pub struct默认情况下仍保持字段私有。如果您需要在公共界面中公开enum数据但又想隐藏详细信息,则需要将(私有)enum包装在pub struct中。
结构和枚举彼此相似。
什么时候使用结构体比使用枚举更好(反之亦然)?有人可以举一个明确的例子,说明使用结构比使用枚举更可取吗?
【问题讨论】:
pub enum 公开所有细节(变体及其字段),pub struct 默认情况下仍保持字段私有。如果您需要在公共界面中公开enum 数据但又想隐藏详细信息,则需要将(私有)enum 包装在pub struct 中。
枚举有多种可能性。结构只有一种可能的“类型”。在数学上,我们说结构是一种产品类型,而枚举是产品的总和。如果您只有一种可能性,请使用结构。例如,空间中的一个点总是将是三个数字。它永远不会是字符串、函数或其他东西。所以它应该是一个包含三个数字的结构。另一方面,如果您正在构建一个数学表达式,它可能是(例如)一个数字或两个由运算符连接的表达式。它有多种可能性,所以它应该是一个枚举。
简而言之,如果结构有效,请使用结构。 Rust 可以围绕它进行优化,任何阅读您的代码的人都会更清楚该值应该被视为什么。
【讨论】:
Enum 是具有一组受限值的类型。
enum Rainbow {
Red,
Orange,
Yellow,
Green,
Blue,
Indigo,
Violet
}
let color = Red;
match color {
Red => { handle Red case },
// all the rest would go here
}
如果需要,您可以将数据存储在 Enum 中。
enum ParseData {
Whitespace,
Token(String),
Number(i32),
}
fn parse(input: String) -> Result<String, ParseData>;
结构是表示事物的一种方式。
struct Window {
title: String,
position: Position,
visible: boolean,
}
现在您可以创建新的Window 对象来代表屏幕上的一个窗口。
【讨论】:
也许解释根本区别的最简单方法是枚举包含“变体”,一次只能拥有一个,而结构体包含一个或多个字段,全部你必须拥有的。
因此,您可以使用enum 来模拟错误代码之类的东西,您一次只能有一个:
enum ErrorCode {
NoDataReceived,
CorruptedData,
BadResponse,
}
如果需要,枚举变量可以包含值。例如,我们可以像这样向ErrorCode 添加一个案例:
enum ErrorCode {
NoDataReceived,
CorruptedData,
BadResponse,
BadHTTPCode(u16),
}
在这种情况下,ErrorCode::BadHTTPCode 的实例始终包含 u16。
这使得每个单独的变体表现得有点像tuple struct or unit struct:
// Unit structs have no fields
struct UnitStruct;
// Tuple structs contain anonymous values.
struct TupleStruct(u16, &'static str);
但是,将它们编写为枚举变体的好处是ErrorCode 的每个案例都可以存储在ErrorCode 类型的值中,如下所示(这对于不相关的结构是不可能的)。
fn handle_error(error: ErrorCode) {
match error {
ErrorCode::NoDataReceived => println!("No data received."),
ErrorCode::CorruptedData => println!("Data corrupted."),
ErrorCode::BadResponse => println!("Bad response received from server."),
ErrorCode::BadHTTPCode(code) => println!("Bad HTTP code received: {}", code)
};
}
fn main() {
handle_error(ErrorCode::NoDataReceived); // prints "No data received."
handle_error(ErrorCode::BadHTTPCode(404)); // prints "Bad HTTP code received: 404"
}
然后您可以在枚举上match 来确定您获得了哪个变体,并根据它是哪个变体执行不同的操作。
相比之下,我上面没有提到的第三种结构是最常用的——这是每个人在简单地说“结构”时所指的结构类型。
struct Response {
data: Option<Data>,
response: HTTPResponse,
error: String,
}
fn main() {
let response = Response {
data: Option::None,
response: HTTPResponse::BadRequest,
error: "Bad request".to_owned()
}
}
请注意,在这种情况下,为了创建 Response,必须为其所有字段指定值。
此外,response 的值的创建方式(即HTTPResponse::Something)意味着HTTPResponse 是一个枚举。它可能看起来像这样:
enum HTTPResponse {
Ok, // 200
BadRequest, // 400
NotFound, // 404
}
【讨论】:
self,并为每个变体创建有效的不同实现。