【问题标题】:Using associated functions in methods accepting trait objects在接受特征对象的方法中使用关联函数
【发布时间】:2018-06-19 01:36:52
【问题描述】:

我正在研究 Rust 特征 LayoutSection,并遇到了一个问题,我必须为该特征创建两个几乎相同的函数:一个是关联函数,一个是方法:section_type() 和 @ 987654326@.

理想情况下,我将只有 section_type() 关联函数,但是 LayoutSection 不能成为特征对象,除非 section_type()where Self: Sized 子句。

但是我需要在使用 trait 对象的方法中使用 section_type(),所以我不得不创建 section_kind(&self),它与 section_type() 完全相同,但它可以在 trait 对象上调用。

我知道这是一个可怕的 hack,必须有一些替代方案,但我想不出任何其他方法来做到这一点。

以下是如何定义和使用这些函数的简化示例:(这里是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() 关联的函数更好。

【问题讨论】:

标签: rust traits


【解决方案1】:

我能够找到使用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
    }
}

Link to the Rust Playground

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 2022-10-05
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多