为了更好地了解Rust,我构建了一个简单的文本编辑器,并使用了以下结构体:
struct File {
rows: Vec<Row>,
filename: Option<String>
}
impl File {
fn row(&self, index: u16) -> &Row{
&self.rows[index as usize]
}
}
struct Row {
string: String,
}
struct EditorState {
file: File,
}
正如您所看到的,我将编辑器的状态保存在一个结构体中,该结构体引用文件,该结构体包含许多行,该结构体包含一个字符串(这些结构体中的每一个都有更多的字段,但我已经删除了与问题无关的字段)
现在我想使我的行可编辑,并添加了以下内容:
impl Row {
fn insert(&mut self, at: u16, c: char) {
let at = at as usize;
if at >= self.string.len() {
self.string.push(c);
} else {
self.string.insert(at, c)
}
}
}
下面是我尝试更新行的方法:
//In the actual functon, I am capturing the keypress,
//get the correct row from the state and pass it and the pressed
// char to row.insert
fn update_row(mut state: &mut EditorState) {
let row = &state.file.row(0);
row.insert(0, 'a');
}
以下代码无法编译:
error[E0596]: cannot borrow `*row` as mutable, as it is behind a `&` reference
从这个错误中,我可以看出问题在于Row应该是可变的,以便我可以编辑它(这是有意义的,因为我正在修改它的String)我不知道a)如何能够修改这里的字符串,以及b)如何在不使row
总是返回可变引用的情况下做到这一点,就像在所有其他情况下一样,我调用row
来读取一行,而不是去写。
3条答案
按热度按时间ie3xauqp1#
下面是
File
的一个更惯用的实现:此处的注意事项:
index
超出界限,您的实现将出现异常。处理这种情况的惯用方法是返回一个Option,get
和get_mut
允许您免费获得该Option。u16
在这里是任意的,除非你真的想提供硬编码的限制。在这种情况下,我不会依赖类型的max值,而是一个常量,这样会使意图更清楚。xe55xuns2#
你想要的是不可能的,你必须写两个函数(注意,我用
usize
代替了u16
--你没有理由把自己限制在每行65536个字符):注意,这是所有Rust代码的共同模式,例如
Vec
有get(idx)
和get_mut(idx)
。lrl1mhuk3#
文件封装行,因此不公开该行。
而是在File中实现方法以对封装的行执行某些操作。
一般来说,程序应该具有如下结构
在您情况下:
代替