返回实现多个特征的对象 - 装饰模式

问题描述 投票:0回答:1

我目前正在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实现的装饰对象。方法加载和扫描都应该可用。

rust decorator traits decltype
1个回答
1
投票

函数只能返回单一类型的值,因此函数返回的类型不能依赖于运行时条件。然而,该类型可以是盒装特征,在这种情况下,存储在框中的值的类型可以改变,只要它实现适当的特征(或特征)。

从您提供的示例代码中,我认为Lexer应该是像trait Lexer: Scan + Load {}这样的特征(或者ScanLoad特征根本不需要存在,而scanload方法可以直接在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 { … })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.