Попытка использовать & себя в программе Rust - PullRequest
0 голосов
/ 09 марта 2019

У меня есть файл с именем info.rs, который содержит небольшую тестовую структуру, предназначенную для представления некоторой базовой информации о файле. Код ниже является обучающим кодом для использования структур:

pub struct FileInfo {
    name: String,
    path: String,
}

impl FileInfo {
    pub fn new(aname: String,apath: String) {
        FileInfo {
            name: aname,
            path: apath
        }
    }

    pub fn get_name(&self) {
       self.name
    }

    pub fn get_path(&self) -> String {
        self.path
    }
}

Согласно документации (и нескольким примерам!), Параметр & self, используемый в вышеприведенных функциях, относится к вызывающей структуре, в данном случае к структуре FileInfo. Цель состоит в том, чтобы мой код main.rs мог получить доступ к имени и пути:

mod info;

use info::FileInfo;

fn main() {
    println!("Listing files in current directory.");

    let fdat = FileInfo::new(String::from("File.txt".),String::from("./File.txt"));

    println!("Name: {}",fdat.get_name());
    println!("Path: {}",fdat.get_path());
}

К сожалению, компиляция завершается со следующими сообщениями:

error[E0507]: cannot move out of borrowed content
  --> src\info.rs:79:9
   |
79 |         self.name
   |         ^^^^^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src\info.rs:83:9
   |
83 |         self.path
   |         ^^^^^^^^^ cannot move out of borrowed content

error: aborting due to 2 previous errors

Это не имеет смысла, потому что код из https://doc.rust -lang.org / rust-by-example / fn / method.html обращается к параметрам & self так же, как и я:

struct Point {
   x: f64,
   y: f64,
}

// Implementation block, all `Point` methods go in here
impl Point {
    // This is a static method
    // Static methods don't need to be called by an instance
    // These methods are generally used as constructors
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }

    // Another static method, taking two arguments:
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    // This is an instance method
    // `&self` is sugar for `self: &Self`, where `Self` is the type of the
    // caller object. In this case `Self` = `Rectangle`
    fn area(&self) -> f64 {
        // `self` gives access to the struct fields via the dot operator
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        // `abs` is a `f64` method that returns the absolute value of the
    // caller
    ((x1 - x2) * (y1 - y2)).abs()
}

    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        2.0 * ((x1 - x2).abs() + (y1 - y2).abs())
    }

    // This method requires the caller object to be mutable
    // `&mut self` desugars to `self: &mut Self`
    fn translate(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;

        self.p1.y += y;
        self.p2.y += y;
    }
}

Этот код компилируется, а мой - нет. Почему это?

Может кто-нибудь сказать мне, что мне здесь не хватает?

Ответы [ 2 ]

6 голосов
/ 09 марта 2019

Есть несколько основ, которые вам нужно освежить, прежде чем разочароваться в языке.

Приведенный выше Артемий дал вам базовое исправление .. f64 реализует Copy и, как таковое, не возникает проблем с владением, когда вы возвращаете их из функции (они просто копируются).

String однако, не реализует Copy, и поэтому ваш код на самом деле говорит "уберите значения String из методов и передайте право собственности вызывающей стороне". Компилятор не позволяет вам сделать это, потому что вы уже позаимствовали структуру FileInfo, вызвав метод.

Ниже приведены два способа (клонировать или вернуть ссылку):

// clone it:
pub fn get_name(&self) -> String {
   self.name.clone() // <-- call `clone()` on the `String` instance to return a new copy out
}

// return a reference:
pub fn get_path(&self) -> &String {
    &self.path
}

Если вы не уверены , почему вышеприведенное работает, то вам нужно снова обратиться к исходному материалу, чтобы понять ссылки и различия между вещами, которые реализуют Copy, и теми, которые этого не делают.

Возможно, вы даже выиграете от понимания Принуждение к разыскиванию , потому что вы также можете вернуть ссылку &str:

// Deref coercion to return a `&str` reference
pub fn get_path(&self) -> &str {
    &self.path
}

Вот он работает на детской площадке

3 голосов
/ 09 марта 2019

Структура из Rust By Example содержит только f64 поля. A f64 реализует черту Copy , поэтому примитив имеет семантическое копирование, а не семантическое перемещение.

Структура в вашем случае содержит String полей, они реализуют только черту Clone. Таким образом, вы должны сделать клон или вернуть ссылку.

Также вы должны увидеть разницу между Copy и Clone и список из Copy разработчиков

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...