2

私は Rust のジェネリクスに頭を悩ませようとしています。さまざまな Web サイトから HTML を抽出するものを書いています。私が欲しいのは次のようなものです:

trait CanGetTitle {
    fn get_title(&self) -> String;
}

struct Spider<T: CanGetTitle> {
    pub parser: T
}

struct GoogleParser;
impl CanGetTitle for GoogleParser {
    fn get_title(&self) -> String {
        "title from H1".to_string().clone()
    }
}

struct YahooParser;
impl CanGetTitle for YahooParser {
    fn get_title(&self) -> String {
        "title from H2".to_string().clone()
    }
}

enum SiteName {
    Google,
    Yahoo,
}

impl SiteName {
    fn from_url(url: &str) -> SiteName {
        SiteName::Google
    }
}

fn main() {
    let url = "http://www.google.com";
    let site_name = SiteName::from_url(&url);
    let spider: Spider<_> = match site_name {
        Google => Spider { parser: GoogleParser },
        Yahoo => Spider { parser: YahooParser }
    };

    spider.parser.get_title();    // fails
}

2 つの異なる型でパラメータ化された s をmatch返すとエラーが発生します。それがパターン マッチの最初のアームの戻り値の型であるため、Spiderそれが返されることを期待しています。Spider<GoogleParser>

spiderそれが anyであることをどのように宣言できますかSpider<T: CanGetTitle>?

4

2 に答える 2

3

spiderそれが anyであることをどのように宣言できますかSpider<T: CanGetTitle>?

それはいけません。spider簡単に言えば、コンパイラは、スタックに格納するためにどれだけのスペースを割り当てる必要があるかわかりません。

代わりに、 trait オブジェクトを使用したいと思うでしょう: Box<CanGetTitle>:

impl<T: ?Sized> CanGetTitle for Box<T>
where
    T: CanGetTitle,
{
    fn get_title(&self) -> String {
        (**self).get_title()
    }
}

fn main() {
    let innards: Box<CanGetTitle> = match SiteName::Google {
        SiteName::Google => Box::new(GoogleParser),
        SiteName::Yahoo => Box::new(YahooParser),
    };
    let spider = Spider { parser: innards };
}
于 2016-12-29T16:49:17.353 に答える