Вектор объектов, принадлежащих признаку

Рассмотрим следующий код:

trait Animal { fn make_sound(&self) -> String; } struct Cat; impl Animal for Cat { fn make_sound(&self) -> String { "meow".to_string() } } struct Dog; impl Animal for Dog { fn make_sound(&self) -> String { "woof".to_string() } } fn main () { let dog: Dog = Dog; let cat: Cat = Cat; let v: Vec = Vec::new(); v.push(cat); v.push(dog); for animal in v.iter() { println!("{}", animal.make_sound()); } } 

Компилятор говорит мне, что v является вектором Animal когда я пытаюсь нажать cat (несоответствие типа)

Итак, как я могу сделать вектор объектов, принадлежащих к признаку, и называет соответствующий метод признаков для каждого элемента?

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

 :22:9: 22:40 error: instantiating a type parameter with an incompatible type `Animal`, which does not fulfill `Sized` [E0144] :22 let mut v: Vec = Vec::new(); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Причина, почему это не является законным, заключается в том, что Vec хранит много объектов T последовательно в памяти. Тем не менее, Animal – это черта, и черты не имеют размера (у Cat и Dog не гарантируется одинаковый размер).

Чтобы решить эту проблему, нам нужно сохранить что-то, что имеет размер в Vec . Наиболее простым решением является обертывание значений в Box , то есть Vec> . Box имеет фиксированный размер («указатель жира», если T – это признак, простой указатель в противном случае).

Вот main :

 fn main () { let dog: Dog = Dog; let cat: Cat = Cat; let mut v: Vec> = Vec::new(); v.push(Box::new(cat)); v.push(Box::new(dog)); for animal in v.iter() { println!("{}", animal.make_sound()); } } 

Вы можете использовать объект ссылочного объекта &Animal для заимствования элементов и сохранения этих объектов-признаков в Vec . Затем вы можете перечислить его и использовать интерфейс признака.

Изменение универсального типа Vec путем добавления символа & перед признаком будет работать:

 fn main() { let dog: Dog = Dog; let cat: Cat = Cat; let mut v: Vec<&Animal> = Vec::new(); // ~~~~~~~ v.push(&dog); v.push(&cat); for animal in v.iter() { println!("{}", animal.make_sound()); } // Ownership is still bound to the original variable. println!("{}", cat.make_sound()); } 

Это здорово, если вы захотите, чтобы исходная переменная сохраняла право собственности и повторно использовала ее позже.

Имейте в виду, что сценарий выше, вы не можете передавать права собственности на dog или cat потому что Vec заимствовал эти конкретные экземпляры в том же объеме.

Введение новой области может помочь справиться с этой конкретной ситуацией:

 fn main() { let dog: Dog = Dog; let cat: Cat = Cat; { let mut v: Vec<&Animal> = Vec::new(); v.push(&dog); v.push(&cat); for animal in v.iter() { println!("{}", animal.make_sound()); } } let pete_dog: Dog = dog; println!("{}", pete_dog.make_sound()); } 
  • Как программа Rust может получать доступ к метаданным из своего пакета Cargo?
  • Как остановить итерацию и вернуть ошибку, когда Iterator :: map возвращает результат: Err?
  • Как включить модуль из другого файла из того же проекта?
  • Как инициализировать поля структуры, которые ссылаются друг на друга
  • Не удается выйти из заемного контента при развертывании
  • Как я могу собрать в массив?
  • Передача изменчивой самостоятельной ссылки на метод принадлежащего ему объекта
  • Как преобразовать вектор байтов (u8) в строку
  • Каков де-факто способ чтения и записи файлов в Rust 1.x?
  • Каковы различия между «String» и «str» Rust?
  • Преобразовать строку в int в Rust?
  • Interesting Posts

    Правильный способ сохранить объединенные соединения в живых (или время их выхода и получить свежие) в течение более длительного времени бездействия для MySQL, приложение Grails 2

    Как преобразовать List в int в Java?

    Вызов `getDrawingCache` возвращает значение null при включении прокрутки

    SearchClick OnCloseListener не работает

    логика остановки слежения

    Установить отключить атрибут на основе условия для Html.TextBoxFor

    Entity Framework 6 с SQLite 3 Code First – не будет создавать таблицы

    # 1055 – Выражение списка SELECT не находится в предложении GROUP BY и содержит неагрегированный столбец, это несовместимо с sql_mode = only_full_group_by

    Как сделать вложенную библиотеку в Windows 7?

    Автоматическое расширение R-фактора в набор переменных индикатора 1/0 для каждого уровня фактора

    Открытые поля и автоматические свойства

    Когда происходит «запуск системы», если используется планировщик заданий с параметром / sc onstart?

    Пользовательский обработчик раздела конфигурации приложения.config

    Использование CSS для эффекта затухания при загрузке страницы

    Как создать нелинейную цветовую палитру / цветную панель?

    Давайте будем гением компьютера.