Created
January 4, 2018 03:21
-
-
Save kyleheadley/6c8860d8fea67c1da2ab18abc6d556b8 to your computer and use it in GitHub Desktop.
Revisions
-
kyleheadley created this gist
Jan 4, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ //! Demo of static "inheritance" //! //! Use trait objects to get dynamic inheritance, //! but casting to a subtype is not explored here //////////////////////////////////////////////////////// // Define Base type, interface, and what is overloadable //////////////////////////////////////////////////////// /// The main type that will be extended struct Basetype<E:BaseExtend> { data: usize, ext: E, } /// Additional data and overloadable functions for subtypes trait BaseExtend : Sized { /// the "overloadable" function from the base interface fn sub_info(s:&Basetype<Self>) -> String { String::from("None") } } /// Convenience for code clarity /// /// allows: fn foo<B:BaseInterface>(b:B) {} /// instead of: fn foo<E:BaseExtend>(b:Basetype<E>) {} trait BaseInterface { fn get_data(&self) -> usize; fn sub_info(&self) -> String; } impl<E:BaseExtend> BaseInterface for Basetype<E>{ /// not overloadable, always inherited fn get_data(&self) -> usize { self.data } /// call the overloadable version fn sub_info(&self) -> String { E::sub_info(self) } } impl BaseExtend for () { // not including functions uses the default defined above } /// non-extended version of the base type type Base = Basetype<()>; impl Base { /// function unique to the base type fn new(a:usize) -> Base {Basetype{ data:a, ext:()}} } ///////////////////////////////////////////////////////////////// // Define some subtypes and their overloaded and unique functions ///////////////////////////////////////////////////////////////// /// additional fields in the subtype struct Subtype1{ thestring: String } impl BaseExtend for Subtype1 { fn sub_info(s:&Basetype<Self>) -> String { s.ext.thestring.clone() } } /// a subtype of the base type type Sub1 = Basetype<Subtype1>; impl Sub1 { /// function unique to this sub type fn new(a:usize,b:String) -> Sub1 { Basetype{ data: a, ext: Subtype1{thestring:b}} } } /// additional fields in the subtype struct Subtype2{thenum:usize} impl BaseExtend for Subtype2 { fn sub_info(s:&Basetype<Self>) -> String { s.ext.thenum.to_string() } } /// a subtype of the base type type Sub2 = Basetype<Subtype2>; impl Sub2 { /// function unique to this sub type fn new(a:usize,b:usize) -> Sub2 { Basetype{data: a, ext: Subtype2{thenum:b}} } } //////////////////////// // Define a Sub-Sub type //////////////////////// struct Subtype<E:SubExtend>{ data: usize, ext: E, } impl<E:SubExtend> BaseExtend for Subtype<E> { fn sub_info(s:&Basetype<Self>) -> String { format!("Sub{}: {}", s.ext.data, E::subsub_info(s)) } } trait SubExtend : Sized { /// No default means this requires an implementation fn subsub_info(s:&Basetype<Subtype<Self>>) -> String; fn say_more(s:&Basetype<Subtype<Self>>) -> String { String::from("more!") } } impl<E:SubExtend> Basetype<Subtype<E>> { // `fn subsub_info` is not part of the interface fn say_more(&self) -> String { E::say_more(self) } } impl SubExtend for () { fn subsub_info(s:&Basetype<Subtype<Self>>) -> String { String::from("None") } } impl Basetype<Subtype<()>>{ fn new() -> Self { Basetype{data:0,ext:Subtype{data:1,ext:()}} } } struct Defiant{msg:String} impl SubExtend for Defiant { fn subsub_info(s:&Basetype<Subtype<Self>>) -> String { s.ext.ext.msg.clone() } fn say_more(s:&Basetype<Subtype<Self>>) -> String { String::from("I don't want to!") } } impl Basetype<Subtype<Defiant>> { fn new() -> Self { Basetype{data:51256,ext:Subtype{data:9289,ext:Defiant{msg:String::from("blah, blah")}}} } } ///////////////////////// // Show that it all works ///////////////////////// /// function that takes any base or sub type /// /// alternately, it could be defined more specifically: /// fn get_sub<E:BaseExtend>(b:Basetype<E>) -> String {b.sub_info()} /// which would allow a where clause to restrict E further fn get_sub(b:&BaseInterface) -> String {b.sub_info()} fn main() { let a = Base::new(2); println!("a base data: {}",a.get_data()); println!("a ext data: {}",get_sub(&a)); let b = Sub1::new(2,String::from("yes")); println!("b base data: {}",b.get_data()); println!("b ext data: {}",get_sub(&b)); let c = Sub2::new(2,3); println!("c base data: {}",c.get_data()); println!("c ext data: {}",get_sub(&c)); let e = Basetype::<Subtype<Defiant>>::new(); println!("e base data: {}",e.get_data()); println!("e ext data: {}",get_sub(&e)); println!("e, say more: {}", e.say_more()); }