#dynamic #oop #cast #traits #interface

nightly no-std dynamic-cast

The fifth pillar of OOP: dynamic casting

6 releases

new 0.1.5 Nov 11, 2024
0.1.4 Sep 12, 2024
0.1.3 Nov 9, 2023

#1394 in Rust patterns

Download history 38/week @ 2024-07-22 179/week @ 2024-09-09 102/week @ 2024-09-16 40/week @ 2024-09-23 41/week @ 2024-09-30 24/week @ 2024-10-07 21/week @ 2024-10-14 13/week @ 2024-10-21 15/week @ 2024-10-28 26/week @ 2024-11-04

77 downloads per month
Used in 2 crates

MIT/Apache

13KB
161 lines

maintenance: experimental

dynamic-cast

The fifth pillar of OOP: dynamic casting.

use dynamic_cast::{SupportsInterfaces, impl_supports_interfaces, dyn_cast_arc};
use std::sync::Arc;

// class Base

#[portrait::make]
trait TBase: SupportsInterfaces {
    fn base_method(&self) -> u8;
}

struct Base {
    data: u8,
}

impl_supports_interfaces!(Base: TBase);

impl TBase for Base {
    fn base_method(&self) -> u8 { self.data }
}

// class Descendant: Base

#[portrait::make]
trait TDescendant: TBase + SupportsInterfaces {
    fn descendant_method(&self) -> u8;
}

struct Descendant {
    base: Base,
    data: u8,
}

impl_supports_interfaces!(Descendant: TBase, TDescendant);

#[portrait::fill(portrait::delegate(Base; self.base))]
impl TBase for Descendant { }

impl TDescendant for Descendant {
    fn descendant_method(&self) -> u8 { self.data }
}

// casting

fn main() {
    let a: Arc<dyn TDescendant> = Arc::new(Descendant { base: Base { data: 1 }, data: 2 });
    assert_eq!(a.descendant_method(), 2);
    assert_eq!(a.base_method(), 1);
    let a_as_base: Arc<dyn TBase> = dyn_cast_arc(a).unwrap();
    assert_eq!(a_as_base.base_method(), 1);
    let a_as_descendant: Arc<dyn TDescendant> = dyn_cast_arc(a_as_base).unwrap();
    assert_eq!(a_as_descendant.descendant_method(), 2);
    assert_eq!(a_as_descendant.base_method(), 1);
}

Dependencies

~39KB