三种调用方式解释
在本节里,通过两个模块mod_bare
和mod_trait
实现及其三种调用方式比较,详细说明衔接关键词trait
作用。
学习内容
- 理解衔接关键词
trait
的重要性 - 掌握衔接关键词
trait
实现的应用方法
篇目
- 基于结构类型的实现:使用实例调用
- 基于衔接特质的实现:使用实例调用
- 基于衔接特质的模块
- 基于衔接特质的实现:作为参数调用
- 题外话
- 浅说面向对象编程、命令式编程和声明式编程
- 数据类型数组
- 泛型函数与方法
- 类型范围关键词
where
- 参考资料
基于结构类型的实现:使用实例调用
从上面图示,可以了解到下面程序文件直接访问模块mod_bare
,该模块是基于结构类型的实现,不存在衔接特质。
// File: examples/bare_hello.rs use mod_trait_exerci::mod_bare::StructType; use mod_trait_exerci::mod_bare::TupleType; fn get_data_from_struct(instances: [StructType; 2]) { let data = instances[0].get_tuple(); assert_eq!(0, data); assert_eq!((0), data); assert_eq!(instances[0], instances[1]); println!("{:?}", instances[0]); println!("{:?}", instances[1]); } fn get_data_from_tuple(instances: [TupleType; 2]) { let data = instances[0].get_tuple(); assert_eq!(0, data); assert_eq!((0), data); assert_eq!(instances[0], instances[1]); println!("{:?}", instances[0]); println!("{:?}", instances[1]); } // clear && cargo run --example bare_hello fn main() { let instances: [StructType; 2] = [Default::default(), StructType{data:0}]; get_data_from_struct(instances); let instances: [TupleType; 2] = [Default::default(), TupleType(0)]; get_data_from_tuple(instances); }
基于衔接特质的实现:使用实例调用
从上面图示,下面程序文件也是直接访问模块mod_trait
本身,与上面应用实例不同,这里通过衔接特质方式实现代码,从代码的关键词use
语句也可以了解到这一点。
比较上面程序文件bare_hello.rs
和下面文件trait_instance_hello.rs
的关键词use
语句,可以看到,上面程序文件里的关键词use
语句访问模块,采用了绝对路径方式,而下面文件既有绝对路径方式,也有相对路径方式。
// File: examples/trait_instance_hello.rs use mod_trait_exerci::mod_trait; use mod_trait::TraitCanal; use mod_trait::StructType; use mod_trait::TupleType; fn get_data_from_struct(instances: [StructType; 2]) { let data = instances[0].get_tuple(); assert_eq!(0, data); assert_eq!((0), data); assert_eq!(instances[0], instances[1]); println!("{:?}", instances[0]); println!("{:?}", instances[1]); } fn get_data_from_tuple(instances: [TupleType; 2]) { let data = instances[0].get_tuple(); assert_eq!(0, data); assert_eq!((0), data); assert_eq!(instances[0], instances[1]); println!("{:?}", instances[0]); println!("{:?}", instances[1]); } // clear && cargo run --example trait_instance_hello fn main() { let instances: [StructType; 2] = [Default::default(), StructType::new(0)]; get_data_from_struct(instances); let instances: [TupleType; 2] = [Default::default(), TupleType::new(0)]; get_data_from_tuple(instances); }
基于衔接特质的模块
从上面图示,可以了解到,下面程序文件也是一个模块mod_where_fn
,该模块应用了模块mod_trait
的功能,注意该文件关键词use
语句只使用了衔接特质TraitCanal
,这也是一种访问其父模块的相对路径方式。它的存在意义是什么?这是为用户提供更加灵活的实现而设计的。这里提供了怎么样使用模块,而不必用户完成实现。
下面代码的方法是一种泛型方法的表达方式,其概念参考下面说明。
下面将会说明关键词where
。在文件mod_where_fn.rs
里的两个函数是两个完全相同的实现,只是语法表达方式不同而已。
// File: src/mod_where_fn.rs use super::mod_trait::TraitCanal; pub fn get_static_type_ref<Type: TraitCanal>(typ: &Type) -> (u32) { typ.get_tuple() } pub fn get_static_type_ref_with_where<Type>(typ: &Type) -> (u32) where Type: TraitCanal { typ.get_tuple() }
基于衔接特质的实现:作为参数调用
从上面图示,可以了解到下面程序文件并不是直接访问模块mod_trait
本身,而是访问中间模块mod_where_fn
完成的,这是一种更加方便和灵活的三层程序设计结构。与模块mod_trait
不同,它实现的功能更多的是数据操作功能,这里称之为“数据模块
”,而这种中间模块mod_where_fn
,它提供更多样化的有实际意义知识性功能,这里称之为“知识模块
”。
无论是什么类型结构,为了获取不同的结构类型属性,都不需要访问其属性名称。
在使用模块mod_where_fn
的函数时,结构类型的实例是作为参数传递给该模块的函数。我们仅仅告诉它我们是‘谁’,我们需要做什么。
模块mod_trait
告诉我们是什么功能,这好比是产品生产原料。模块mod_where_fn
解决了怎么做问题,这好比是为用户预先打造的特定产品,当然用户也可以自己制造自己需要的产品。这里程序文件说明了要做什么事情,这好比作为用户使用现成的产品。
// File: examples/trait_where_hello.rs use mod_trait_exerci::mod_where_fn; use mod_trait_exerci::mod_trait; use mod_trait::StructType; use mod_trait::TupleType; fn static_struct_ref_with_where(instance: &StructType) { let data = mod_where_fn::get_static_type_ref_with_where(instance); assert_eq!(0, data); assert_eq!((0), data); } fn static_tuple_ref_with_where(instance: &TupleType) { let data = mod_where_fn::get_static_type_ref_with_where(instance); assert_eq!(0, data); assert_eq!((0), data); } // clear && cargo run --example trait_where_hello fn main() { let instance: StructType = Default::default(); static_struct_ref_with_where(&instance); let instance: TupleType = Default::default(); static_tuple_ref_with_where(&instance); }
题外话
浅说面向对象编程、命令式编程和声明式编程
面向对象编程回答了是什么,命令式编程回答了怎么做,而声明式编程回答了做什么。
数据类型数组
在Rust语言里,数组是一种基本数据类型。
泛型函数与方法
在类型理论中,泛型称之为参数多态(parametric polymorphism),对于给定参数(parametric)能够有多种形式(poly是多,morph是形态)的函数或类型。
在Rust语言里,泛型是一种非常广泛采用的技术,不仅应用函数与方法关键词fn
,也应用衔接特质关键词trait
等等。其目的是,减少代码重复。
类型范围关键词where
关键词where
用于向泛型类型添加约束,并为编译器提供解决问题所需的信息!