我目前正在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
}
我不知道是否可以静态推断出返回类型为decltype(lex)
之类的东西。实施该方法的通用方法是什么?有什么可以改善的?
要澄清:我想返回decltype(lex)
,因为单个Lexer也可能具有多个特征,例如:
pub trait Load {
fn load<T : Load>(&self, keywords: &String);
}
impl Load for Lexer {
fn load<Lexer>(&self, keyword : &String) {
...
}
}
我希望也返回一个带有Load trait实现的修饰对象。方法加载和扫描都应该可用。
答案 0 :(得分:1)
函数只能返回一种类型的值,因此函数返回的 type 不能取决于运行时条件。但是,该类型可能是装箱的特征,在这种情况下,只要实现适当的一个或多个特征,存储在框中的值的类型就可以更改。
从您提供的示例代码中,我认为Lexer
应该是trait Lexer: Scan + Load {}
这样的特征(或者也许Scan
和Load
特征不需要完全存在,scan
和load
方法可以直接在Lexer
中定义)。然后,您的build
函数应该只返回一个带框的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 { … })
}
}