use plusplus::{class, InConstruction, DowncastTo};
class!{
crate as plusplus;
pub class ObjectZero {
string: String;
pub fn new() -> ObjectZero<InConstruction> {
init_class! {
string: "hello".into(),
another_field: 26,
}
}
pub(crate) another_field: i32;
pub fn set_string(&mut self, str: String) {
self.string = str;
}
}
}
mod object_one {
use plusplus::{class, InConstruction};
class!{
crate as plusplus;
pub class ObjectOne: super::ObjectZero {
string_one: String;
pub fn new() -> ObjectOne<InConstruction> {
init_class! {
superclass: super::ObjectZero::new(),
string_one: String::new(),
}
}
pub fn print_example(&self) {
println!("hi from ObjectOne");
}
override super::ObjectZero {
pub fn set_string(&mut self, str: String) {
self.super_set_string(str.clone());
self.string_one = str;
}
}
}
}
impl ObjectOne {
pub fn string_one(&self) -> &str {
&self.string_one
}
}
}
use object_one::ObjectOne;
class!{
crate as plusplus;
pub class ObjectTwo: ObjectOne {
string_two: String;
pub fn new(two: impl Into<String>) -> ObjectTwo<InConstruction> {
init_class! {
superclass: object_one::ObjectOne::new(),
string_two: two.into(),
}
}
override ObjectOne {
pub fn print_example(&self) {
self.super_print_example();
println!("hello from ObjectTwo");
}
}
override ObjectZero {
pub fn set_string(&mut self, str: String) {
self.super_set_string(str.clone());
self.string_two = str;
}
}
}
}
fn main() {
let object_two = ObjectTwo::new("hello!").finish();
object_two.print_example();
println!();
let object_as_one = object_two.upcast();
object_as_one.print_example();
println!();
object_as_one.my_print_example();
println!();
let mut object_as_base = object_as_one.upcast();
let new_str = "sets all strings!!";
object_as_base.set_string(new_str.to_string());
let object_as_two = object_as_base
.downcast_to::<ObjectOne>().unwrap()
.downcast_to::<ObjectTwo>().unwrap();
assert_eq!(object_as_two.string, new_str);
assert_eq!(object_as_two.string_one(), new_str);
assert_eq!(object_as_two.string_two, new_str);
}