Return 实现多个特征的对象 - 装饰器模式
Return object implementing multiple traits - decorator pattern
我目前正在用 Rust 实现装饰器模式。
在 Scala 中,我们可以通过如下特征实现方法链:
new Scanner
with Whitespaces
with Keywords
我想在 Rust 中做同样的事情。因此,扫描仪的不同特征:
pub struct Lexer();
pub trait Scan {
fn scan(&self, start: &String) -> DomainTags;
}
pub struct Keywords<T> {
decorated: T
}
impl<T: Scan> Scan for Keywords<T> {
fn scan(&self, start: &String) -> DomainTags {
...
}
}
pub struct Whitespaces<T> {
decorated: T
}
impl<T: Scan> Scan for Whitespaces<T> {
fn scan(&self, start: &String) -> DomainTags {
...
}
}
但是因为我想用这样的方法构建我的词法分析器:
pub fn build() -> ??? {
let lex = Lexer();
let lex = Keyword {
decorated: Whitespaces {
decorated: lex
}
};
lex
}
我不知道是否可以将 return 类型静态推导为类似 decltype(lex)
的类型。实施该方法的常用方法是什么?哪些方面可以改进?
澄清一下:我想returndecltype(lex)
,因为对于单个词法分析器我可能也有多个特征,比如:
pub trait Load {
fn load<T : Load>(&self, keywords: &String);
}
impl Load for Lexer {
fn load<Lexer>(&self, keyword : &String) {
...
}
}
而且我希望 return 一个带有 Load 特性实现的修饰对象。方法加载和扫描都应该可用。
一个函数只能 return 一种类型的值,因此您的函数所生成的 type return 不能依赖于运行时条件。但是,该类型可能是盒装特征,在这种情况下,存储在框中的值的类型可能会更改,前提是它实现了适当的特征(或多个特征)。
根据您提供的示例代码,我认为 Lexer
应该是像 trait Lexer: Scan + Load {}
这样的特征(或者 Scan
和 Load
特征不根本不需要存在 scan
和 load
方法可以直接在 Lexer
中定义)。那么你的 build
函数应该只是 return 一个盒装的 Lexer
:
pub trait Lexer {
fn scan (&self, start: &String) -> DomainTags;
fn load (&self, keyword : &String);
}
pub struct Keywords<T> {
decorated: T
}
impl<T: Lexer> Lexer for Keywords<T> {
…
}
pub struct Whitespaces<T> {
decorated: T
}
impl<T: Lexer> Lexer for Whitespaces<T> {
…
}
pub fn build (cond: bool) -> Box<dyn Lexer> {
if cond {
Box::new (Whitespaces { … })
} else {
Box::new (Keywords { … })
}
}
我目前正在用 Rust 实现装饰器模式。 在 Scala 中,我们可以通过如下特征实现方法链:
new Scanner
with Whitespaces
with Keywords
我想在 Rust 中做同样的事情。因此,扫描仪的不同特征:
pub struct Lexer();
pub trait Scan {
fn scan(&self, start: &String) -> DomainTags;
}
pub struct Keywords<T> {
decorated: T
}
impl<T: Scan> Scan for Keywords<T> {
fn scan(&self, start: &String) -> DomainTags {
...
}
}
pub struct Whitespaces<T> {
decorated: T
}
impl<T: Scan> Scan for Whitespaces<T> {
fn scan(&self, start: &String) -> DomainTags {
...
}
}
但是因为我想用这样的方法构建我的词法分析器:
pub fn build() -> ??? {
let lex = Lexer();
let lex = Keyword {
decorated: Whitespaces {
decorated: lex
}
};
lex
}
我不知道是否可以将 return 类型静态推导为类似 decltype(lex)
的类型。实施该方法的常用方法是什么?哪些方面可以改进?
澄清一下:我想returndecltype(lex)
,因为对于单个词法分析器我可能也有多个特征,比如:
pub trait Load {
fn load<T : Load>(&self, keywords: &String);
}
impl Load for Lexer {
fn load<Lexer>(&self, keyword : &String) {
...
}
}
而且我希望 return 一个带有 Load 特性实现的修饰对象。方法加载和扫描都应该可用。
一个函数只能 return 一种类型的值,因此您的函数所生成的 type return 不能依赖于运行时条件。但是,该类型可能是盒装特征,在这种情况下,存储在框中的值的类型可能会更改,前提是它实现了适当的特征(或多个特征)。
根据您提供的示例代码,我认为 Lexer
应该是像 trait Lexer: Scan + Load {}
这样的特征(或者 Scan
和 Load
特征不根本不需要存在 scan
和 load
方法可以直接在 Lexer
中定义)。那么你的 build
函数应该只是 return 一个盒装的 Lexer
:
pub trait Lexer {
fn scan (&self, start: &String) -> DomainTags;
fn load (&self, keyword : &String);
}
pub struct Keywords<T> {
decorated: T
}
impl<T: Lexer> Lexer for Keywords<T> {
…
}
pub struct Whitespaces<T> {
decorated: T
}
impl<T: Lexer> Lexer for Whitespaces<T> {
…
}
pub fn build (cond: bool) -> Box<dyn Lexer> {
if cond {
Box::new (Whitespaces { … })
} else {
Box::new (Keywords { … })
}
}