为了约束类型参数,为什么需要一个特征?

问题描述:

为什么在下面的代码中需要特质?没有特征的注释变体不会编译,即使它看起来好像具有相同的可用信息。为了约束类型参数,为什么需要一个特征?

trait ReliabilityConstructor<T> { 
    fn new(a: T) -> Reliability; 
} 

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] 
struct Reliability { 
    alpha: i8, 
} 

//impl<T> Reliability 

impl<T> ReliabilityConstructor<T> for Reliability 
where 
    f64: std::convert::From<T>, 
{ 
    fn new(a: T) -> Reliability { 
     let mut a_f64 = f64::from(a); 
     a_f64 = if a_f64 < -1f64 { 
      -1f64 
     } else if a_f64 > 1f64 { 
      1f64 
     } else { 
      a_f64 
     }; 
     Reliability { alpha: (100f64 * a_f64) as i8 } 
    } 
} 

fn main() { 
    println!("{:?}", Reliability::new(-1)); 
} 

刚刚从From改变性状Into(因为From<T> for U意味着Into<U> for T) - 其意图是多少更清晰:

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] 
struct Reliability { 
    alpha: i8, 
} 

impl Reliability { 
    fn new<T: Into<f64>>(a: T) -> Reliability { // <T> is only here 
     let mut a_f64: f64 = a.into(); // into() is used here 
     a_f64 = if a_f64 < -1f64 { 
      -1f64 
     } else if a_f64 > 1f64 { 
      1f64 
     } else { 
      a_f64 
     }; 
     Reliability { alpha: (100f64 * a_f64) as i8 } 
    } 
} 

fn main() { 
    println!("{:?}", Reliability::new(-1)); 
} 
+0

谢谢,这无疑变得更具可读性和摆脱的特质。我想这也意味着可靠性实施成,这是一个很好的触摸:) –

那是因为你对特征定义,而不是结构定义中定义的类型参数。为了摆脱的特质,你需要移动T到结构本身:

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] 
struct Reliability<T> { 
    alpha: i8, 
} 

impl<T> Reliability<T> where f64: std::convert::From<T> { 
    fn new(a: T) -> Reliability<T> { 
     let mut a_f64 = f64::from(a); 
     a_f64 = if a_f64 < -1f64 { 
      -1f64 
     } else if a_f64 > 1f64 { 
      1f64 
     } else { 
      a_f64 
     }; 
     Reliability { alpha: (100f64 * a_f64) as i8 } 
    } 
} 

fn main() { 
    println!("{:?}", Reliability::new(-1)); 
} 

那说,这就提出了一个不同的问题 - Reliability在定义或实现任何地方实际上并未使用T,使它会与此错误翻倒:

error[E0392]: parameter `T` is never used 
--> <anon>:2:24 
    | 
2 |  struct Reliability<T> { 
    |      ^unused type parameter 
    | 
    = help: consider removing `T` or using a marker such as `std::marker::PhantomData` 

error: aborting due to previous error 

编辑:写这个答案之后,我意识到自己的问题 - 你不是要限制的结构,你只是想约束的方法。在这种情况下,它更容易!

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] 
struct Reliability { 
    alpha: i8, 
} 

impl Reliability { 
    fn new<T>(a: T) -> Reliability where f64: std::convert::From<T> { 
     let mut a_f64 = f64::from(a); 
     a_f64 = if a_f64 < -1f64 { 
      -1f64 
     } else if a_f64 > 1f64 { 
      1f64 
     } else { 
      a_f64 
     }; 
     Reliability { alpha: (100f64 * a_f64) as i8 } 
    } 
} 

fn main() { 
    println!("{:?}", Reliability::new(-1)); 
}