在trait中定义一个方法,该方法返回Self的默认实现。

3

我希望拥有以下功能

trait Policy {
    fn eval(&self, k: u32) -> bool;

    fn default() -> Box<dyn Policy>
    where
        Self: Sized,
    {
        Box::new(MaxPolicy { max: 2 })
    }
}

struct MaxPolicy {
    max: u32,
}

impl Policy for MaxPolicy {
    fn eval(&self, k: u32) -> bool {
        println!("MaxPolicy");
        k < self.max
    }
}

#[test]
fn max_policy() {
    let p = MaxPolicy { max: 2 };
    assert!(!p.eval(3));
}

#[test]
fn default_policy() {
    let p = Policy::default();
    assert!(!p.eval(3));
}

(游乐场)

以下内容无法编译:

error[E0283]: type annotations needed
  --> src/lib.rs:31:13
   |
4  |     fn default() -> Box<dyn Policy>
   |        -------
5  |     where
6  |         Self: Sized,
   |               ----- required by this bound in `Policy::default`
...
31 |     let p = Policy::default();
   |             ^^^^^^^^^^^^^^^ cannot infer type
   |
   = note: cannot resolve `_: Policy`

是否有可能改变方法来使其工作?对于特质对象来说,是否有可能有一个返回Self的实现方法呢?如果不能,为什么呢?


Policy::default() 应该返回哪种类型? - Shepmaster
任何实现了 Policy 接口的类型,都需要被 Box 包装。即使将具体类型,例如 MaxPolicy 放在那里,它也无法编译通过(https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=03fd001b07747366ac4d480613a650c5)。 - Victor Ermolaev
2个回答

2

哇,我对这个语法不太熟悉,比我的枚举方法更简洁。 - Victor Ermolaev
如果您想要向default()返回的内容添加标记,需要显式地写出trait名称,例如, fn default() -> Box<dyn Policy + Send> - Victor Ermolaev

0

我构建了一个绕过方法,具有类似的优秀API

trait Policy {
    fn eval(&self, k: u32) -> bool;
}

struct MaxPolicy {
    max: u32,
}

impl Policy for MaxPolicy {
    fn eval(&self, k: u32) -> bool {
        println!("MaxPolicy");
        k < self.max
    }
}

struct MinPolicy {
    min: u32,
}

impl Policy for MinPolicy {
    fn eval(&self, k: u32) -> bool {
        println!("MinPolicy");
        k > self.min
    }
}

enum PolicyEnum {
    Custom(Box<dyn Policy>),
    Default,
}

impl PolicyEnum {
    const DEFAULT: MaxPolicy = MaxPolicy { max: 4 };
}

impl Policy for PolicyEnum {
    fn eval(&self, k: u32) -> bool {
        match self {
            PolicyEnum::Custom(p) => p.eval(k),
            PolicyEnum::Default => Self::DEFAULT.eval(k),
        }
    }
}

游乐场

有了这个,就可以做到:

#[test]
fn default() {
    let p = PolicyEnum::Default;

    assert!(p.eval(3));
}

#[test]
fn custom() {
    let p = PolicyEnum::Custom(Box::new(MinPolicy{min: 4}));

    assert!(p.eval(5));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接