לדלג לתוכן

2.3 - גבולות ספרייה ותאימות מימושים - פתרון

פתרון constructor ששומר על הטווח

השדה הפרטי מונע מלקוח מחוץ למודול ליצור Port לא מאומת. המימוש הציבורי היחיד ליצירה מבצע את הבדיקות לפני בניית הערך.

mod ports {
    use std::fmt;
    #[derive(Debug, PartialEq)]
    pub struct Port(u16);

    impl Port {
        pub fn new(value: u32) -> Option<Self> {
            let value = u16::try_from(value).ok()?;
            if value == 0 { return None; }
            Some(Self(value))
        }
        pub fn number(&self) -> u16 { self.0 }
    }

    impl fmt::Display for Port {
        fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(formatter, "{}", self.0)
        }
    }
}

fn main() {
    assert!(ports::Port::new(0).is_none());
    assert_eq!(ports::Port::new(1).unwrap().number(), 1);
    assert_eq!(ports::Port::new(65535).unwrap().number(), 65535);
    assert!(ports::Port::new(65536).is_none());
    println!("{}", ports::Port::new(8080).unwrap());
}

הכינוי PortAlias אינו מוסיף בדיקה או זהות טיפוס חדשה; אפשר להציב בו אפס ככל u16. המעטפת מגדירה החלטת API מקומית שמותר לנו לתת לה Display. הטווח שבחרנו הוא מדיניות הטיפוס הלימודי, ולא טענה שכל שימוש ברשת אוסר את המספר אפס בכל הקשר.