目前,将扩展方法添加到另一个模块中的类型(即使该模块在子模块中)的唯一方法是定义一个新特征并为该类型实现它。然而,这非常笨拙,因为方法的数量变得很大:
trait Ops {
fn parse_list_item(&self, current_item: ListItemInfo)
-> ParseResult<(Document, ListItemInfo)>;
fn parse_list_item_content(&self) -> ParseResult<Document>;
}
impl<'a> Ops for MarkdownParser<'a> {
fn parse_list_item(&self, current_item: ListItemInfo)
-> ParseResult<(Document, ListItemInfo)> {
// ...
}
fn parse_list_item_content(&self) -> ParseResult<Document> {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
你必须写两次方法签名。如果它发生变化,您还必须在多个地方更新它。它还增加了很多噪音。
我认为宏会有所帮助,但我不知道如何macro_rules!为函数中的参数列表编写正确的模式。这是我到目前为止所拥有的:
#![feature(macro_rules)]
struct Foo;
macro_rules! ops (
($(fn $name:ident($($args:tt)*) -> $ret:ty $body:block)+) => (
trait Ops {
$(fn $name($($args)*) -> $ret;)+
}
impl Ops for Foo {
$(fn $name($($args)*) -> $ret $body)+
}
)
)
mod ops {
ops! {
fn method1(&self) -> int {
10
}
fn method2(&self, i: int) -> () {
println!("{}", i + self.method1());
}
}
pub fn run_test() {
Foo.method2(22);
}
}
fn main() {
ops::run_test();
}
Run Code Online (Sandbox Code Playgroud)
它以相当讨厌的消息失败:
/tmp/rs/ops/src/main.rs:8:27: 8:31 error: expected type, found token INTERPOLATED(NtTT(ptr::P<ast::TokenTree>{ptr: box TTTok(codemap::Span{lo: codemap::BytePos(337u32), hi: codemap::BytePos(338u32), expn_id: codemap::ExpnId(4294967295u32)}, BINOP(AND))}))
/tmp/rs/ops/src/main.rs:8 $(fn $name($($args)*) -> $ret;)+
^~~~
Run Code Online (Sandbox Code Playgroud)
它可能值得一个错误报告,因为错误消息非常令人生畏,但是,我没有看到另一种按原样传递参数的方法。它似乎与此问题有关,但是,我希望有一种解决方法,例如 在这种情况下。
有什么建议?