我如何 'force' 结构来实现相同的特征?

How do I 'force' structs to implement the same traits?

我有以下内容:

pub struct OpBStruct {
    title: String,
    output_vale: i32,
}

impl OpBStruct {
    pub fn new_OpB(in_title: String, in_output_vale: i32) -> OpBStruct {
        OpBStruct {
            title: in_title,
            output_vale: in_output_vale,
        }
    }
}

pub struct OpCStruct {
    title: String,
    another_value: String,
    output_vale: i32,
}

impl OpCStruct {
    pub fn new_OpC(in_title: String, in_another_value: String, in_output_vale: i32) -> OpCStruct {
        OpCStruct {
            title: in_title,
            another_value: in_another_value,
            output_vale: in_output_vale,
        }
    }
}

impl A {
    pub fn new_A(in_name: String, in_operator: Op) -> A {
        A {
            name: in_name,
            operator: in_operator,
        }
    }
}

pub enum Op {
    OpB(OpBStruct),
    OpC(OpCStruct),
}

pub struct A {
    name: String,
    operator: Op,
}

impl A {
    pub fn new_A(in_name: String, in_operator: Op) -> A {
        A {
            name: in_name,
            operator: in_operator,
        }
    }
}

OpBStructOpCStruct 的确切结构是任意的,可以是任何东西。

如何确保 OpBStructOpCStruct 实现特定特征?

trait OpTrait {    
    pub fn get_op_output(&self) -> i32;
}

我考虑制作一种构造函数来检查 OpTrait 特征要求,这将是创建 Op 实例的唯一方法,但每个运算符需要不同的初始化参数并且无法在 Rust 中为函数指定可变数量的输入。

这样的事情是行不通的,因为无法输入初始化参数:

pub fn new_op<T: OpTrait>(operator: T) {
    //  --snip--
}

我考虑过使用在 A 上实现的 new_A 方法来检查 in_operator 是否实现了特征,但我也不知道该怎么做。

正确的模式是什么?如果有 none,我可以只为每个 Op 实现特性,而不用围绕它的任何接口。

使用单元测试将是一种相当直接的方式来强制执行您想要结构上的给定特征。您可以通过隐式测试代码来完成,但是一个小的实用函数可以更清楚地表达意图。

如果您在其余代码中指示了函数的特征输入,则无需单元测试它可能会很自然地出现。该测试的优点是让您有机会显式检查特征实现的一些不变量。

struct A {
    val: u8,
}


struct B {
    val: u32,
}

trait ExpandToU64 {
    fn to_u64(&self) -> u64;
}

impl ExpandToU64 for A {
    fn to_u64(&self) -> u64
    {
        self.val as u64
    }
}

fn trait_tester<E>(a: E)
    where E: ExpandToU64
{
    // the utility function doesn't have to even use the trait...
    // but you probably want to exercise the logic a bit
    //let v = a.to_u64();
    let v = 24u64;
    println!("{:?}", v);
}

#[test]
fn test_needs_trait_ExpandToU64() {
    let a = A { val:1 };
    trait_tester(a);

    let b = B { val:2 };
    trait_tester(b);
    // This fails with a compile error
    //  "the trait `ExpandToU64` is not implemented for `B`"
}

我还建议编写一个测试,但是您可以编写一个函数,该函数对类型具有通用性但不带参数:

struct X {}

trait Y {
    fn yo();
}

fn is_y<T: Y>(){}

然后您可以添加以下行来进行检查

is_y::<X>();

仅当 X 实现 Y.

时才会编译