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 {} 这样的特征(或者 ScanLoad 特征不根本不需要存在 scanload 方法可以直接在 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 { … })
    }
}