
30.1 类型状态模式Typestate Pattern30.1.1 基本概念类型状态模式使用类型系统在编译期强制状态转换规则。usestd::marker::PhantomData;// 状态标记structLocked;structUnlocked;// 门的类型状态structDoorState{_state:PhantomDataState,}implDoorLocked{fnnew()-Self{println!(门已锁定);Door{_state:PhantomData,}}fnunlock(self)-DoorUnlocked{println!(门已解锁);Door{_state:PhantomData,}}}implDoorUnlocked{fnopen(self){println!(门已打开);}fnlock(self)-DoorLocked{println!(门已锁定);Door{_state:PhantomData,}}}fnmain(){letdoorDoor::Locked::new();letdoordoor.unlock();door.open();// ❌ 编译错误不能直接打开锁定的门// let door Door::Locked::new();// door.open();}30.1.2 实际应用构建器模式structUnset;structSetT(T);structConfigBuilderName,Port{name:Name,port:Port,}implConfigBuilderUnset,Unset{fnnew()-Self{ConfigBuilder{name:Unset,port:Unset,}}}implPortConfigBuilderUnset,Port{fnname(self,name:String)-ConfigBuilderSetString,Port{ConfigBuilder{name:Set(name),port:self.port,}}}implNameConfigBuilderName,Unset{fnport(self,port:u16)-ConfigBuilderName,Setu16{ConfigBuilder{name:self.name,port:Set(port),}}}implConfigBuilderSetString,Setu16{fnbuild(self)-Config{Config{name:self.name.0,port:self.port.0,}}}structConfig{name:String,port:u16,}fnmain(){letconfigConfigBuilder::new().name(MyApp.to_string()).port(8080).build();println!(配置: {} on port {},config.name,config.port);// ❌ 编译错误缺少必需字段// let config ConfigBuilder::new().build();}30.2 幽灵数据PhantomData30.2.1 基本用法usestd::marker::PhantomData;structSlicea,T{start:*constT,end:*constT,_marker:PhantomDataaT,}impla,TSlicea,T{fnnew(slice:a[T])-Self{Slice{start:slice.as_ptr(),end:unsafe{slice.as_ptr().add(slice.len())},_marker:PhantomData,}}}30.2.2 所有权标记usestd::marker::PhantomData;structOwnedT{data:*mutT,_marker:PhantomDataT,}implTDropforOwnedT{fndrop(mutself){unsafe{std::ptr::drop_in_place(self.data);}}}30.3 泛型关联类型GAT30.3.1 基本语法traitContainer{typeItemawhereSelf:a;fngeta(aself,index:usize)-OptionSelf::Itema;}structVecContainerT{data:VecT,}implTContainerforVecContainerT{typeItemaaTwhereT:a;fngeta(aself,index:usize)-OptionSelf::Itema{self.data.get(index)}}fnmain(){letcontainerVecContainer{data:vec![1,2,3],};ifletSome(item)container.get(1){println!(Item: {},item);}}30.3.2 实际应用迭代器traitLendingIterator{typeItemawhereSelf:a;fnnexta(amutself)-OptionSelf::Itema;}structWindowsMutdata,T{data:datamut[T],size:usize,pos:usize,}impldata,TLendingIteratorforWindowsMutdata,T{typeItemaamut[T]whereSelf:a;fnnexta(amutself)-OptionSelf::Itema{ifself.posself.sizeself.data.len(){returnNone;}letslicemutself.data[self.pos..self.posself.size];self.pos1;Some(slice)}}30.4 const 泛型30.4.1 基本用法structArrayT,constN:usize{data:[T;N],}implT,constN:usizeArrayT,N{fnlen(self)-usize{N}}fnmain(){letarrArray{data:[1,2,3,4,5],};println!(长度: {},arr.len());}30.4.2 编译期计算structMatrixT,constROWS:usize,constCOLS:usize{data:[[T;COLS];ROWS],}implT,constROWS:usize,constCOLS:usizeMatrixT,ROWS,COLS{fndimensions(self)-(usize,usize){(ROWS,COLS)}}implT:std::ops::AddOutputTCopy,constN:usizestd::ops::AddforMatrixT,N,N{typeOutputSelf;fnadd(self,other:Self)-Self::Output{letmutresultself;foriin0..N{forjin0..N{result.data[i][j]result.data[i][j]other.data[i][j];}}result}}30.5 类型级编程30.5.1 类型级数字traitNat{}structZero;structSuccN:Nat(std::marker::PhantomDataN);implNatforZero{}implN:NatNatforSuccN{}typeOneSuccZero;typeTwoSuccOne;typeThreeSuccTwo;traitAddRhs:Nat:Nat{typeOutput:Nat;}implN:NatAddZeroforN{typeOutputN;}implN:Nat,M:NatAddSuccMforNwhereN:AddM,{typeOutputSuccNasAddM::Output;}30.5.2 类型级列表traitTypeList{}structNil;structConsHead,Tail:TypeList(std::marker::PhantomData(Head,Tail));implTypeListforNil{}implHead,Tail:TypeListTypeListforConsHead,Tail{}typeListConsi32,ConsString,Consbool,Nil;30.6 利用类型系统编码业务规则30.6.1 单位类型structMeters(f64);structKilometers(f64);implMeters{fnto_kilometers(self)-Kilometers{Kilometers(self.0/1000.0)}}implKilometers{fnto_meters(self)-Meters{Meters(self.0*1000.0)}}fnmain(){letdistanceMeters(5000.0);letkmdistance.to_kilometers();// ❌ 编译错误类型不匹配// let sum Meters(100.0) Kilometers(1.0);}30.6.2 状态机structDraft;structPublished;structArchived;structPostState{content:String,_state:PhantomDataState,}implPostDraft{fnnew(content:String)-Self{Post{content,_state:PhantomData,}}fnpublish(self)-PostPublished{Post{content:self.content,_state:PhantomData,}}}implPostPublished{fnarchive(self)-PostArchived{Post{content:self.content,_state:PhantomData,}}}implPostArchived{fndelete(self){println!(文章已删除);}}fnmain(){letpostPost::Draft::new(内容.to_string());letpostpost.publish();letpostpost.archive();post.delete();}常见误区与陷阱误区 1过度使用类型状态// ❌ 不好过度复杂structState1;structState2;structState3;// ... 10 个状态// ✅ 好适度使用enumState{State1,State2,State3,}误区 2忘记 PhantomData// ❌ 不好编译器警告未使用的类型参数structWrapperT{data:*constu8,}// ✅ 好使用 PhantomDatastructWrapperT{data:*constu8,_marker:PhantomDataT,}实战练习练习 30.1实现类型安全的 SQL 查询构建器参考答案structNoWhere;structWithWhere;structQueryW{table:String,where_clause:OptionString,_marker:PhantomDataW,}implQueryNoWhere{fnfrom(table:str)-Self{Query{table:table.to_string(),where_clause:None,_marker:PhantomData,}}fnwhere_clause(self,clause:str)-QueryWithWhere{Query{table:self.table,where_clause:Some(clause.to_string()),_marker:PhantomData,}}}implQueryWithWhere{fnexecute(self)-String{format!(SELECT * FROM {} WHERE {},self.table,self.where_clause.as_ref().unwrap())}}fnmain(){letqueryQuery::from(users).where_clause(age 18).execute();println!({},query);}本章小结类型状态模式在编译期强制状态转换规则PhantomData标记类型参数的所有权和生命周期GAT泛型关联类型支持更灵活的抽象const 泛型编译期常量作为类型参数类型级编程在类型层面进行计算业务规则编码利用类型系统防止业务逻辑错误零成本抽象类型系统的检查在编译期完成