[英]How can I specify that a trait function takes an argument implementing the trait?
I created an abstract data type for vectors in metric space but the compiler complains because it doesn't recognize that the implementation as an argument is of this type. 我为度量空间中的向量创建了抽象数据类型,但是编译器抱怨,因为它不认识到作为参数的实现就是这种类型。
trait MetricPoint {
fn square_distance(&self, other: &MetricPoint) -> f64;
}
struct RNPoint {
coordinates: Vec<f64>,
}
impl RNPoint {
fn new(coordinates: &[f64]) -> RNPoint {
RNPoint {
coordinates: coordinates.to_vec(),
}
}
}
impl MetricPoint for RNPoint {
fn square_distance(self: &RNPoint, other: &RNPoint) -> f64 {
let min_len = self.coordinates.len().min(other.coordinates.len());
let mut sum = 0.0;
for i in 0..min_len {
let diff = self.coordinates[i] - other.coordinates[i];
sum += diff * diff;
}
sum
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn square_distance() {
let p1 = RNPoint::new(&[0.0, 0.0]);
let p2 = RNPoint::new(&[1.0, 0.0]);
let d = p1.square_distance(&p2);
assert_eq!(d, 1.0)
}
}
The compiler: 编译器:
error[E0053]: method `square_distance` has an incompatible type for trait
--> points/src/lib.rs:19:44
|
2 | fn square_distance(&self, other: &MetricPoint) -> f64;
| ------------ type in trait
...
19 | fn square_distance(self:&RNPoint,other:&RNPoint)->f64 {
| ^^^^^^^^ expected trait MetricPoint, found struct `RNPoint`
|
= note: expected type `fn(&RNPoint, &dyn MetricPoint) -> f64`
found type `fn(&RNPoint, &RNPoint) -> f64`
Why it doesn't recognize that an RNPoint
is an MetricPoint
? 为什么不认识到RNPoint
是MetricPoint
?
You are not far from something that compiles and pass your test. 您距离编译并通过测试的地方并不远。 Just change: 只是改变:
fn square_distance(&self, other: &MetricPoint) -> f64;
to 至
fn square_distance(&self, other: &Self) -> f64;
and optionnally 然后选择
fn square_distance(self: &RNPoint, other: &RNPoint) -> f64
to 至
fn square_distance(self: &RNPoint, other: &Self) -> f64
By writing Self
, you are specifying the type of the current structure. 通过编写Self
,您可以指定当前结构的类型。 It's more generic and readable. 它更具通用性和可读性。
Thanks. 谢谢。 As some said but Hugo more clearly the solution is the self. 正如某些人所说,但雨果更明确的是解决方案是自我。 Here is the final code: 这是最终代码:
trait Metric {
fn distance(&self, other: &Self) -> f64;
}
struct RNPoint {
coordinates: Vec<f64>,
}
impl RNPoint {
fn new(coordinates: &[f64]) -> RNPoint {
RNPoint {
coordinates: coordinates.to_vec(),
}
}
}
impl Metric for RNPoint {
fn distance(&self, other: &Self) -> f64 {
let sum:f64=self.coordinates.iter()
.zip(other.coordinates.iter())
.map(|(&c1, &c2)| {
let diff = c1 - c2;
diff * diff
})
.sum();
sum.sqrt()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_distance() {
let p1 = RNPoint::new(&[0.0, 0.0]);
let p2 = RNPoint::new(&[1.0, 0.0]);
let d = p1.distance(&p2);
assert_eq!(d, 1.0)
}
}
About the abstract class I wrote Abstract Data Type but stack overflow changed it and I didn't notice. 关于抽象类,我写了抽象数据类型,但是堆栈溢出改变了它,我没有注意到。 Sorry about 为......感到抱歉
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.