什么是面向对象
面向对象编程(Object-Oriented Programming, 简称OOP)是一种编程范式, Rust 是一个00后的年轻语言, 它还没被设计出来时, 就已经有很多的编程范式了, 什么过程式编程, 函数式编程, 当然也包括面向对象编程, 所以作者在设计 Rust 的时候, 不可避免的会参考这些已经存在的编程范式
面向对象是一个比较宽泛的概念, 在很多资料中会认为只有像Java那种(class/extends/interface/implements)才叫面向对象, 但其实我觉得只要符合面向对象编程特点的编程方式, 都可以称之为面向对象编程
面向对象编程的特点: 封装
继承(复用)
多态
对象包含数据和行为
面向对象的程序是由对象组成的, 一个对象包含数据和操作这些数据的过程, 这些过程通常被称为方法或操作
rust
struct Cat {
// 成员属性
name: String,
age: u32,
}
impl Cat {
// 实例化
fn new(name: String, age: u32) -> Self {
Self { name, age }
}
// 成员方法
fn catch_mouse(&self) {
println!("抓老鼠");
}
}
封装: 隐藏实现细节
rust
struct Cat {
name: String,
age: u32,
}
impl Cat {
fn new(name: String, age: u32) -> Self {
Self { name, age }
}
fn catch_mouse(&self) {
println!("抓老鼠");
}
}
fn main() {
let c = Cat::new(String::from("tom"), 10);
// 不需要管这个方法如何实现的, 只需要知道这个方法的作用即可
c.catch_mouse();
}
继承: 代码复用和共享
rust
trait Animal {
fn eat(&self) {
println!("动物需要吃东西");
}
fn breathe(&self) {
println!("动物需要呼吸氧气");
}
}
struct Cat {
name: String,
age: u32,
}
impl Cat {
fn new(name: String, age: u32) -> Self {
Self { name, age }
}
fn catch_mouse(&self) {
println!("抓老鼠");
}
}
// 可以看做继承了 Animal
impl Animal for Cat {}
fn main() {
let c = Cat::new(String::from("tom"), 10);
c.catch_mouse();
c.eat();
c.breathe();
}
多态: 代码的灵活和扩展性
rust
trait Animal {
fn eat(&self) {
println!("动物需要吃东西");
}
}
struct Cat {}
impl Animal for Cat {
fn eat(&self) {
println!("猫吃鱼");
}
}
struct Dog {}
impl Animal for Dog {
fn eat(&self) {
println!("狗吃骨头");
}
}
// 不管是猫吃东西(Cat eat)还是狗吃东西(Dog eat)
// 都可以看做是动物在吃东西(Animal eat)
// 对比代码, 不管传入的a具体是什么, 只要 a 实现了 Animal 这个 trait 就行
fn animal_eat_something<T: Animal>(a: T) {
a.eat();
}
fn main() {
let c = Cat{};
let d = Dog{};
animal_eat_something(c);
animal_eat_something(d);
}
rust
struct Cat {}
struct Dog {}
fn cats_eat_fish(c: Cat) {
println!("猫吃鱼");
}
fn dogs_eat_bones(d: Dog) {
println!("狗吃骨头:");
}
// 如果有100种动物就要定义100个不同的方法
fn main() {
let c = Cat{};
let d = Dog{};
cats_eat_fish(c);
dogs_eat_bones(d);
}
面向对象: 适配器模式的实现
在Rust程序设计语言这本书中, 有一个状态模式的例子 那我就写一个更易于理解的适配器模式的例子吧
rust
use std::collections::HashMap;
////////////////////////////
///// 可缓存的特性 /////
////////////////////////////
trait Cacheable {
fn get_by_key(&self, key:String);
fn set_by_key(&mut self, key:String, value: String);
fn clear(&mut self); // 为了易读和方便就不使用 Refcell 了, 直接传入可变引用算了
}
////////////////////////////
///// 文件缓存具体实现 /////
////////////////////////////
struct FileCache {
file_path: String, // 缓存保存到哪个文件中
}
impl FileCache {
fn new(file_path: String) -> FileCache {
FileCache { file_path }
}
fn read_cache_from_file(&self, key:String) {
println!("从文件中读取缓存, {}", key);
}
fn write_cache_to_file(&self, key:String, value: String) {
println!("将要缓存的数据写入文件中, {}, {}", key, value);
}
fn delete_cache_file(&self) {
println!("删除缓存文件, {}", self.file_path);
}
}
////////////////////////////
///// 文件缓存适配器 ///////
////////////////////////////
struct FileCacheAdapter {
driver: FileCache
}
impl FileCacheAdapter {
fn new(file_path: String) -> FileCacheAdapter {
FileCacheAdapter {
driver: FileCache::new(file_path)
}
}
}
impl Cacheable for FileCacheAdapter {
fn get_by_key(&self, key:String) {
self.driver.read_cache_from_file(key);
}
fn set_by_key(&mut self, key:String, value: String) {
self.driver.write_cache_to_file(key, value);
}
fn clear(&mut self) {
self.driver.delete_cache_file();
}
}
// 内存缓存具体实现: 可以没有具体实现, 直接将功能直接放到适配器中,
// 因为在适配器模式中, 具体实现一般都是私有的, 适配器才是公开的API
// struct MemoryCache { }
///////////////////////////
///// 内存缓存适配器 //////
///////////////////////////
struct MemoryCacheAdapter {
cache_map: HashMap<String, String>
}
impl MemoryCacheAdapter {
fn new() -> MemoryCacheAdapter {
MemoryCacheAdapter {
cache_map: HashMap::new(),
}
}
}
impl Cacheable for MemoryCacheAdapter {
fn get_by_key(&self, key: String) {
let val = self.cache_map.get(&key);
println!("从内存中读取缓存: {:?}", val);
}
fn set_by_key(&mut self, key:String, value: String) {
self.cache_map.insert(key, value);
println!("将缓存放入内存中: {:?}", self.cache_map);
}
fn clear(&mut self) {
self.cache_map.clear();
println!("清除内存中的缓存: {:?}", self.cache_map);
}
}
// 如果还需要扩展更多缓存方式
// struct MysqlCache { /* 具体实现 */ }
// struct MysqlCacheAdapter { /* 适配器 */ }
// impl Cacheable for MysqlCacheAdapter { /* 为适配器实现接口 */ }
// struct PgsqlCache { /* 具体实现 */ }
// struct PgsqlCacheAdapter { /* 适配器 */ }
// impl Cacheable for PgsqlCacheAdapter { /* 为适配器实现接口 */ }
fn main() {
let mut cache_adapter = MemoryCacheAdapter::new();
// let mut cache_adapter = FileCacheAdapter::new("./1.cache.json".to_string());
cache_adapter.get_by_key("key1".to_string());
cache_adapter.set_by_key("key1".to_string(), "value1".to_string());
cache_adapter.get_by_key("key1".to_string());
cache_adapter.clear();
}