WedX - журнал о программировании и компьютерных науках

Передать ссылку на саму функцию содержащегося объекта

Я пытаюсь понять модель собственности Руста. Я пытаюсь передать ссылку на содержащий объект при вызове функции в структуре.

Вот моя структура:

pub struct Player {}

impl Player {
    pub fn receive(self, app: &App) {

    }
}

Как видите, receive ожидает ссылку на объект App.

pub struct App {
    pub player: Player,
}

impl App {
    pub fn sender(self) {
        // how to call player.test() and pass self as a reference?
        self.player.receive(&self);
    }
}

Приведенный выше код дает мне «использование частично перемещенного значения: self». Это имеет смысл, потому что App имеет семантику перемещения, поэтому значение было перемещено в функцию sender при ее вызове.

Если я изменю его так, чтобы sender вместо этого принимал ссылку на self, я получаю «невозможно выйти из заимствованного содержимого», что также имеет смысл, потому что мы заимствовали ссылку на self, когда перешли в функцию sender.

Так что же мне делать? Я понимаю, почему я не могу сохранить ссылку на App внутри Player, поскольку это привело бы к двусвязной структуре. Но я должен иметь возможность заимствовать ссылку и выполнять с ней операции, не так ли?

Я не нашел ответа в официальном руководстве.

Я решил это, передав self в качестве ссылки в receive. Но что, если я хочу, чтобы app был изменяемым в receive? Я не могу передать self как изменяемый в sender, потому что я также заимствую player как изменяемый.

29.04.2016

Ответы:


1

поскольку App имеет семантику перемещения, поэтому значение было перемещено в функцию sender при ее вызове.

Это правда, что он был перемещен в sender, но это сообщение не об этом. Поскольку Player::receive принимает self по значению, вам фактически пришлось разложить app и переместить player из него, чтобы иметь возможность вызывать receive. На тот момент app сформирован наполовину; у него нет допустимого значения для player! Если receive попытается получить доступ к app.player, будет использована недопустимая память.

не может выйти из заимствованного содержимого [...], потому что мы заимствовали ссылку на self, когда вошли в функцию sender.

Правильно, что связано с вышеизложенным. Поскольку мы заимствуем App, мы не можем выйти player из него, оставив App в недопустимом состоянии.

Я должен иметь возможность позаимствовать ссылку и выполнить с ней операции, не так ли?

И вы можете, пока вещь, на которую вы ссылаетесь, полностью сформирована на этом этапе. В вышеприведенной экспозиции также было две подсказки:

  1. # P7 #
    # P8 #
  2. # P9 #
    # P10 #

Конечно, более практичным решением будет перейти на прием ссылок (&self).

Но что, если я хочу, чтобы app был изменен в receive?

Ага! Вы не можете заимствовать *self как изменяемый более одного раза за раз. Однако решения на самом деле в основном те же! Разбейте свой App на более мелкие, неперекрывающиеся части или отделите player от self перед вызовом метода.

29.04.2016

2

Один из способов использовать решение Shepmaster

отключите player от self перед вызовом метода.

Поместить player в Option:

impl App {
    pub fn sender(&mut self) {
        let mut player = self.player.take();
        player.receive(&mut self);
        self.player = Some(player);
    }
}

Последний ресурс - использовать RefCell.

29.04.2016
Новые материалы

Объяснение документов 02: BERT
BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


Для любых предложений по сайту: [email protected]