Continuing the discussion from Most coveted Rust features:
Abstract base classes. The best solution I can currently come up with is using a wrapper type but this doesn't work cross-crate (IIRC, it should eventually work cross-module):
use std::fs::File;
use std::ops::{Deref, DerefMut};
use std::io::Write;
struct AbstractTextbox<T> {
inner: T,
text: String
}
trait ConcreteTextbox {
fn on_update(&mut self) { }
}
impl<T> AbstractTextbox<T> where Self: ConcreteTextbox {
pub fn new(inner: T) -> Self {
AbstractTextbox {
inner: inner,
text: String::new()
}
}
pub fn append(&mut self, text: &str) {
self.text.push_str(text);
self.on_update();
}
pub fn get_text(&self) -> &str {
&self.text
}
}
impl<T> Deref for AbstractTextbox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<T> DerefMut for AbstractTextbox<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.inner
}
}
pub struct PersistedTextboxData {
file: File,
dirty: bool
}
type PersistedTextbox = AbstractTextbox<PersistedTextboxData>;
impl PersistedTextbox {
pub fn save(&mut self) {
if self.dirty {
self.dirty = false;
self.file.set_len(0).unwrap();
let txt = self.get_text().to_string();
self.file.write_all(txt.as_bytes()).unwrap();
}
}
pub fn new() -> PersistedTextbox {
AbstractTextbox::new(PersistedTextboxData {
file: File::create("/tmp/textbox.txt").unwrap(),
dirty: false,
})
}
}
impl ConcreteTextbox for PersistedTextbox {
fn on_update(&mut self) {
self.dirty = true;
}
}
fn main() {
let mut t = PersistedTextbox::new();
t.append("a");
t.save();
}