我正在处理Rust特性LayoutSection
,并遇到了一个问题,我必须为这个特性制作两个几乎完全相同的函数:一个是相关函数,一个是那个方法:section_type()
和section_kind(&self)
。
理想情况下,我只会使用section_type()
关联函数,但LayoutSection
无法成为特征对象,除非section_type()
具有where Self: Sized
子句。
但是我需要在使用特征对象的方法中使用section_type()
,因此我被迫创建section_kind(&self)
,这与section_type()
完全相同,但可以调用它特质对象。
我知道这是一个可怕的黑客,并且必须有一些替代方案,但我无法想到其他任何方式来做到这一点。
以下是如何定义和使用这些功能的简化示例:(此处为Rust Playground)
fn main() {
print_generic_info::<Header>(None);
}
fn print_generic_info<S: LayoutSection>(game: Option<Game>) {
if let Some(s) = game {
let section = s.get_section::<S>();
}
// The reason I wanted to use a type parameter in `Game::get_section`,
// rather than pass a `SectionType`, is because I'm doing something
// like this later on:
// let section = <S as LayoutSection>::with_offset(...);
}
struct Game;
impl Game {
fn get_section<S: LayoutSection>(&self) -> Option<&LayoutSection> {
Some(match <S as LayoutSection>::section_type() {
SectionType::Header => unimplemented!(),
})
}
}
#[derive(Debug)]
enum SectionType {
Header
}
trait LayoutSection {
fn section_kind(&self) -> SectionType;
fn section_type() -> SectionType
where
Self: Sized;
fn print_generic_info(&self) {
println!("Type: {:?}", self.section_kind());
}
}
struct Header;
impl LayoutSection for Header {
fn section_kind(&self) -> SectionType {
SectionType::Header
}
fn section_type() -> SectionType {
SectionType::Header
}
}
什么是更好的替代方案?我想使用关联常量来存储SectionType
,但是使用那些仍然不允许将LayoutSection
用作特征对象。但是类似的东西甚至比section_type()
相关函数更好。
答案 0 :(得分:0)
我能够找到一个使用SectionType
枚举而不是使用类型参数的解决方案。我希望有一个名为SectionType::with_offset
的关联函数,但我可以向SectionType::with_offset
添加SectionType
方法。这是更新后的示例:
fn main() {
print_generic_info(None, &SectionType::Header);
}
fn print_generic_info(game: Option<Game>, section_type: &SectionType) {
if let Some(s) = game {
let section = s.get_section(section_type);
// Now I can do this:
let other_section = section_type.with_offset(0);
}
}
struct Game;
impl Game {
fn get_section(&self, section_type: &SectionType) -> Option<&LayoutSection> {
Some(match section_type {
SectionType::Header => unimplemented!(),
})
}
}
#[derive(Debug)]
enum SectionType {
Header
}
impl SectionType {
fn with_offset(&self, offset: u64) -> Box<LayoutSection> {
match self {
SectionType::Header => Box::new(Header),
}
}
}
trait LayoutSection {
fn section_kind(&self) -> SectionType;
fn print_generic_info(&self) {
println!("Type: {:?}", self.section_kind());
}
}
struct Header;
impl LayoutSection for Header {
fn section_kind(&self) -> SectionType {
SectionType::Header
}
}