我仍在学习Rust,并试图使用rust-cssparser
来重用源库中定义的impl,但遇到了编译错误cannot define inherent impl for a type outside of the crate where the type is defined
。当然,库使用use super::Token;
,但我需要use cssparser::{ Token };
,并且不知道如何解决。https://github.com/servo/rust-cssparser/blob/master/src/serializer.rs#L503-L552
摘录:
impl<'a> Token<'a> {
/// Categorize a token into a type that determines when `/**/` needs to be inserted
/// between two tokens when serialized next to each other without whitespace in between.
///
/// See the `TokenSerializationType::needs_separator_when_before` method.
pub fn serialization_type(&self) -> TokenSerializationType {
use self::TokenSerializationTypeVariants::*;
TokenSerializationType(match *self {
Token::Ident(_) => Ident,
Token::AtKeyword(_) | Token::Hash(_) | Token::IDHash(_) => AtKeywordOrHash,
...
})
}
}
基于帮助、note: define and implement a trait or new type instead
和一些搜索,我尝试了下面的几个变体,但我对编译错误的处理毫无进展或更深。谢谢你的帮助。
use cssparser::{
Token as Tkn,
// Token
};
// struct Token<'a>(Tkn<'a>); // requires changing lots of refs
type Token<'a> = Tkn<'a>;
您不能重新实现在机箱外声明的类型。这是因为您在impl <'a> Token<'a>
中添加的任何函数对于使用Token
的任何其他板条箱来说都是未知的。通过重新实现,相同类型的实现在板条箱之间会有所不同,这就是为什么它是不允许的。
解决方案
这里正确的做法是用serialization_type
函数声明一个特性,比如SerializationType
,然后为Token
实现SerializationType
。
pub trait SerializationType<'a> {
fn serialization_type(&self) -> TokenSerializationType;
}
impl<'a> SerializationType<'a> for Token<'a> {
fn serialization_type(&self) -> TokenSerializationType {
use self::TokenSerializationTypeVariants::*;
TokenSerializationType(match *self {
Token::Ident(_) => Ident,
Token::AtKeyword(_) | Token::Hash(_) | Token::IDHash(_) => AtKeywordOrHash,
...
})
}
}
替代解决方案
另一种解决方案是创建一个新类型。请注意,别名类型不会创建新类型,因此会触发相同的错误。
pub type CustomToken<'a> = Token<'a>;
您应该将Token<'a>
封装到一个结构中,然后实现该结构:
struct CustomToken<'a>(Token<'a>);
impl <'a> CustomToken<'a> {
fn serialization_type(&self) -> TokenSerializationType {
use self::TokenSerializationTypeVariants::*;
TokenSerializationType(match *self {
Token::Ident(_) => Ident,
Token::AtKeyword(_) | Token::Hash(_) | Token::IDHash(_) => AtKeywordOrHash,
...
})
}
}
在我看来,基于特征的解决方案更好。