简体   繁体   English

在Rust特性中实现构造函数

[英]Implementing constructor function in rust trait

I'd like to define several similar types struct A(Option), struct B(Option) etc., where a floating point value is constrained within a range. 我想定义几种类似的类型struct A(Option),struct B(Option)等,其中浮点值限制在一个范围内。 The structs may differ further a little bit in their behaviour, but the constructor of each type ist the same: it returns Some(value) if the value is already constrained, otherwise None. 这些结构的行为可能略有不同,但是每种类型的构造函数都相同:如果值已经受到约束,则返回Some(value),否则返回None。 To avoid having to implement each constructor individually for each type; 为了避免必须为每种类型分别实现每个构造函数; I'd like to implement it in the trait. 我想在特征中实现它。 Is this really not possible? 这真的不可能吗?

Using the following below, I am told that Self is not a function and that I 使用下面的内容,我被告知Self不是函数,并且我

can't use Self as a constructor, you must use the implemented struct 不能将Self用作构造函数,必须使用已实现的struct

.

#[derive(Debug)]
struct A(Option<f64>);

trait Constrained {
    const MIN: f64;
    const MAX: f64;

    fn is_constrained(value: f64) -> bool {
        value >= Self::MIN && value <= Self::MAX
    }

    fn new(value: f64) -> Self where Self: std::marker::Sized {
        if Self::is_constrained(value) {
            Self(Some(value))
        } else {
            Self(None)
        }
    }
}

impl Constrained for A {
    const MIN: f64 = -360.0;
    const MAX: f64 = 360.0;
/*
    fn new(value: f64) -> A {
        if Self::is_constrained(value) {
            Self(Some(value))
        } else {
            Self(None)
        }
    }
*/
}


fn main() {
    let some_val: A = A::new(1000.0);
    println!("{:?}", some_val);
}

Commenting out the implementation of the new function in the trait (starting before where), and uncommenting the impl for each indivdiual struct works of course, but this leads to unncessary code doubling for each type. 注释掉特征中新功能的实现(在where之前开始),并取消对每个单独struct作品的impl的注释,当然,但这会导致每种类型的代码不必要地加倍。 Is there anything possible or planned to generalize this? 有什么可能或计划将其概括吗?

From your code, it seems that you have several requirements: 从您的代码看来,您有几个要求:

  • The implementing struct must provide storage for a field Option<f64> 实现结构必须为字段Option<f64>提供存储
  • The implementation must provide two constants, MAX and MIN. 该实现必须提供两个常量MAX和MIN。

What you are really looking for is const generics on the struct. 您真正要寻找的是结构上的const泛型。 Unfortunately, it is still a highly unstable and incomplete nightly feature as of August 2019. Alternatively, you might resort to macros. 不幸的是,截至2019年8月,它仍然是一个高度不稳定且不完整的夜间功能。或者,您可以诉诸宏。

The derive_more crate allows you to derive From<Option<f64>> for each implementating struct tuple that contains exactly one field. derive_more板条箱允许您为每个只包含一个字段的实现结构元组派生From<Option<f64>> That is, you might want this: 也就是说,您可能需要这样做:

#[derive(From)]
pub struct A(Option<f64>);

// just a blanket impl with two consts

Then your trait can require implementors to also implement From<Option<f64>> , which is the required constructor here: 然后,您的特征可以要求实现者也实现From<Option<f64>> ,这是此处所需的构造函数:

pub trait Constrained : From<Option<f64>> {
    const MAX: f64;
    const MIN: f64;

    // Your is_constrained method
    // Use Self::from(None) instead of Self(None)
}

This improves your attempt in that From can be automatically derived from an existing macro (it is also an idiomatic constructor in Rust style). 这可以改善您的尝试,因为From可以自动从现有的宏派生(它也是Rust风格的惯用构造函数)。

The whole point is that Rust traits must not impose any requirements on the precise structure of the implementors. 整个观点是,Rust特性不能对实现者的精确结构施加任何要求。 It is also valid for some implementor to have another unused (or irrelevant to Constrained ) field; 对于某些实施者来说,拥有另一个未使用(或与Constrained无关)字段也是有效的; then your trait is not flexible enough. 那么你的特质就不够灵活。


Side note: it also appears that your trait might be inconvenient to pass around in the future, since trait const items aren't very flexible. 旁注:由于特质const项不是很灵活,因此将来也很难传递您的特质。 Perhaps you will want to use macros-by-example to generate the whole definition+impl in the future. 也许将来您会希望使用宏示例来生成整个definition + impl。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM