Rust на примерах — страница 38 из 65

let mut dolly: Sheep = Animal::new("Dolly");

// ЗАДАНИЕ ^ Попробуйте убрать аннотацию типа

dolly.talk();

dolly.shear();

dolly.talk();

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

АтрибутDerive

Компилятор способен предоставить основные реализации для некоторых типажей с помощью атрибута #[derive]. Эти типажи могут быть реализованы вручную, если необходимо более сложное поведение.

Ниже приводится список выводимых типажей:

   • Типажи сравнения:Eq, PartialEq, Ord, PartialOrd

   • Clone, для создания T из &T с помощью копии.

   • Copy, чтобы создать тип семантикой копирования, вместо семантики перемещения.

   • Hash, чтобы вычислить хеш из &T.

   • Default, чтобы создать пустой экземпляр типа данных.

   • Debug, чтобы отформатировать значение с помощью {:?}.

// `Centimeters`, кортежная структура, которую можно сравнить

#[derive(PartialEq, PartialOrd)]

struct Centimeters(f64);

// `Inches`, кортежная структура, которую можно напечатать

#[derive(Debug)]

struct Inches(i32);

impl Inches {

fn to_centimeters(&self) -> Centimeters {

let &Inches(inches) = self;

Centimeters(inches as f64 * 2.54)

}

}

// `Seconds`, кортежная структура без дополнительных атрибутов

struct Seconds(i32);

fn main() {

let _one_second = Seconds(1);

// Ошибка: `Seconds` не может быть напечатана; не реализован типаж `Debug`

//println!("Одна секунда выглядит как: {:?}", _one_second);

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

// Ошибка: `Seconds` нельзя сравнить; не реализован типаж `PartialEq`

//let _this_is_true = (_one_second == _one_second);

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

let foot = Inches(12);

println!("Один фут равен {:?}", foot);

let meter = Centimeters(100.0);

let cmp =

if foot.to_centimeters() < meter {

"меньше"

} else {

"больше"

};

println!("Один фут {} одного метра.", cmp);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Смотрите также:

derive

Возврат типажа сdyn

Компилятору Rust нужно знать сколько места занимает результат каждой функции. Это обозначает, что все ваши функции имеют конкретный тип результата. В отличие от других языком, если у вас есть типаж, например Animal, то вы не можете написать функцию, которая вернёт Animal, по той причине, что разные реализации этого типажа будут занимать разное количество памяти.

Однако есть простой обходной путь. Вместо не посредственного возврата типажа-объекта, наши функции могут возвращать Box, который содержит некоторую реализацию Animal. box - это просто ссылка на какую-то память в куче. Так как размер ссылки известен статически и компилятор может гарантировать, что она указывает на аллоцированную в куче реализацию, мы можем вернуть типаж из нашей функции!

Rust пытается быть предельно явным, когда он выделяет память в куче. Так что если ваша функция возвращает указатель-на-типаж-в-куче, вы должны дописать к возвращаемому типу ключевое слово dyn, например Box.

struct Sheep {}

struct Cow {}

trait Animal {

// Сигнатура метода объекта

fn noise(&self) ->&'static str;

}

// Реализуем типаж `Animal` для `Sheep`.

impl Animal for Sheep {

fn noise(&self) ->&'static str {

"baaaaah!"

}

}

// Реализуем типаж `Animal` для `Cow`.

impl Animal for Cow {

fn noise(&self) ->&'static str {

"moooooo!"

}

}

// Вернём некоторую структуру, которая реализует `Animal`, но которая не известна в момент компиляции.

fn random_animal(random_number: f64) -> Box {

if random_number < 0.5 {

Box::new(Sheep {})

} else {

Box::new(Cow {})

}

}

fn main() {

let random_number = 0.234;

let animal = random_animal(random_number);

println!("Вы выбрали случайное животное и оно говорит {}", animal.noise());

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Перегрузка операторов

В Rust, множество операторов могут быть перегружены с помощью типажей. То есть, некоторые операторы могут использоваться для выполнения различных задач на основе вводимых аргументов. Это возможно, потому что операторы являются синтаксическим сахаром для вызова методов. Например, оператор + в a + b вызывает метод add (как в a.add(b)). Метод add является частью типажа Add. Следовательно, оператор + могут использовать все, кто реализуют типаж Add.

Список типажей, таких как Add, которые перегружают операторы, доступен здесь.

use std::ops;

struct Foo;

struct Bar;

#[derive(Debug)]

struct FooBar;

#[derive(Debug)]

struct BarFoo;

// Типаж `std::ops::Add` используется для указани