Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

items from traits can only be used if the trait is implemented and in scope

Tags:

scope

rust

traits

I tried to implement the Observer pattern from Heads-up Design Patterns, which was originally written in Java:

use std::cell::RefCell;
use std::rc::Rc;
use std::borrow::BorrowMut;

trait Subject {
    fn registerObserver(&mut self, observer: Rc<RefCell<Observer>>);
    fn removeObserver(&mut self, observer: Rc<RefCell<Observer>>);
    fn notifyObserver(&self, observer: Rc<RefCell<Observer>>);
}

trait Observer {
    fn update(&mut self, data: f32);
}


struct Teacher {
    observers: Vec<Rc<RefCell<Observer>>>,
    data: f32,
}
impl Teacher {
    pub fn print(&self) {
        println!("teacher = {:}", self.data);
    }
}
impl Subject for Teacher {
    fn registerObserver(&mut self, observer: Rc<RefCell<Observer>>) {
        self.observers.push(observer);
    }
    fn removeObserver(&mut self, observer: Rc<RefCell<Observer>>) {
        println!("Teacher.removeObserver(...) not implemented yet...")
    }
    fn notifyObserver(&self, observer: Rc<RefCell<Observer>>) {
        for observer in self.observers {
            let mut loc_obs = observer.borrow_mut();
            loc_obs.update(self.data);
        }
    }
}

struct Student {
    data: f32,
}
impl Student {
    pub fn print(&self) {
        println!("student = {:}", self.data);
    }
}
impl Observer for Student {
    fn update(&mut self, data: f32) {
        self.data = data;
    }
}



fn main() {
    let mut teacher = Teacher {
        observers: Vec::new(),
        data: 42.,
    };
    teacher.print();
}

Playground

The compiler tells me

error[E0599]: no method named `update` found for type `&mut std::rc::Rc<std::cell::RefCell<Observer + 'static>>` in the current scope
  --> src/main.rs:35:21
   |
35 |             loc_obs.update(self.data);
   |                     ^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `update`, perhaps you need to implement it:
           candidate #1: `Observer`

Where is my error?

like image 414
shiMusa Avatar asked Oct 25 '17 20:10

shiMusa


Video Answer


1 Answers

use std::borrow::BorrowMut;

You've brought in the trait BorrowMut, which defines the trait method BorrowMut::borrow_mut, shadowing the inherent method RefCell::borrow_mut. You can tell this because your type is not what you expect:

for type &mut std::rc::Rc<std::cell::RefCell<Observer + 'static>>

The simplest fix is to remove that import. You can also disambiguate between them.

You then have further issues around trying to take ownership of a borrowed value and lots of non-idiomatic names that create boatloads of warnings. You should address all of those.

like image 63
Shepmaster Avatar answered Nov 01 '22 13:11

Shepmaster