可能是一个措辞不好的问题,但这里举个例子:
给出这些结构;
pub struct Poll {
_lat: f64,
_lon: f64,
_at: i64,
_heading: f64,
_speed: f64,
}
pub struct Waypoint {
_lat: f64,
_lon: f64,
}
和这个特性;
pub trait CoordMeasure {
fn dist_to(&self, other: &Self ) -> f64;
}
如何像我一样避免重复此代码?
impl CoordMeasure for Poll {
fn dist_to(&self, other: &Poll) -> f64 {
super::core::distance(self, other)
}
}
impl CoordMeasure for Waypoint {
fn dist_to(&self, other: &Waypoint) -> f64 {
super::core::distance(self, other)
}
}
我有两次调用相同的函数距离。
pub fn distance<T: Coord>(a: &T, b: &T ) -> f64 {
let lat1_rads = (90.0 - a.lat()).to_radians();
let lat2_rads = (90.0 - b.lat()).to_radians();
let lon_rads = (b.lon() - a.lon()).to_radians();
let cos_of_lat1 = lat1_rads.cos();
let cos_of_lat2 = lat2_rads.cos();
let sin_of_lat1 = lat1_rads.sin();
let sin_of_lat2 = lat2_rads.sin();
let cos_of_lons = lon_rads.cos();
let equation = ((cos_of_lat2 * cos_of_lat1) + (sin_of_lat2 * sin_of_lat1 * cos_of_lons)).acos();
6334009.6 * equation
}
它只是重复一行代码,但它可能是一个更好的例子。在C#中,这个代码将在Waypoint和Poll派生自的抽象类中编写一次。处理这种情况的惯用Rust方法是什么?
答案 0 :(得分:3)
通用实现是可能的:
impl<T: Coord> CoordMeasure for T {
fn dist_to(&self, other: &T) -> f64 {
super::core::distance(self, other)
}
}
但在这种特殊情况下,您应该完全删除CoordMeasure
并在Coord
上将其作为默认方法实现:
trait Coord {
…
fn dist_to(&self, other: &Self) -> f64 {
super::core::distance(self, other) // or move its contents in here
}
}
您可能还想制作它以便能够处理其他类型的other
(我认为other
必须与self
必须属于同一类型的任何直接原因:
fn dist_to<Other: Coord>(&self, other: &Other) -> f64 {
let lat1_rads = (90.0 - self.lat()).to_radians();
let lat2_rads = (90.0 - other.lat()).to_radians();
let lon_rads = (b.lon() - self.lon()).to_radians();
let cos_of_lat1 = lat1_rads.cos();
let cos_of_lat2 = lat2_rads.cos();
let sin_of_lat1 = lat1_rads.sin();
let sin_of_lat2 = lat2_rads.sin();
let cos_of_lons = lon_rads.cos();
let equation = ((cos_of_lat2 * cos_of_lat1) + (sin_of_lat2 * sin_of_lat1 * cos_of_lons)).acos();
6334009.6 * equation
}