一个简单的代码如下,显然从逻辑上canvas的size和shape的generic的类型无关(假定无关)。当然,实现上由于静态分发是为所有用到的generic生成函数,所以有关。所以才有了这个问题。
求教!在保证静态分发的前提下,要怎么修改,才能使得我可以不指定shape的情况下,获取canvas的size呢?
struct Canvas<T: Shape> {
shape: T,
thickness: f64,
}
trait Plane {
fn get_dimensions() -> usize;
fn get_volume(&self) -> f64;
}
trait Shape {
fn get_area(&self) -> f64;
fn get_diameter(&self) -> f64;
}
struct Circle {
r: f64,
}
impl Shape for Circle {
fn get_area(&self) -> f64 {
self.r * self.r * 3.1415927
}
fn get_diameter(&self) -> f64 {
2.0 * self.r * 3.1415927
}
}
impl<T: Shape> Plane for Canvas<T> {
// 仅对于Canvas是3,比如impl Plane for ABC,可能就是2(不用太在意逻辑,大概是这个意思)
fn get_dimensions() -> usize {
3
}
fn get_volume(&self) -> f64 {
self.shape.get_area() * self.thickness
}
}
fn get_canvas_size() {
// Canvas::get_dimensions(); // error
Canvas::<Circle>::get_dimensions(); // work,但是显然返回值与shape种类无关,而与canvas有关
}
1
共 7 条评论, 1 页
评论区
写评论作为结题,写一下最终的做法吧。感谢“苦瓜小仔”大佬的思路。最终还是拆成了两个trait,但是为了逻辑上的完整,将二者结合为一个trait。如下,也就是说“WholePlane”是我之后使用该类型时需要用到的trait bound。
也或许最后就直接放弃,选择动态分发了。除了有一点点的调用费用,动态分发真的挺完美的。
--
👇
苦瓜小仔
感谢回答!拓宽了我的思路,trait const这个用法我居然是第一次听说,学习了。
其实倒不是必不必要的问题,因为源代码保证一定有一个实现了trait“Shape”的类似于struct “BasicShape”的存在。所以对于任意这类型的结构体(比如例子中的Canvas和ABC),一定可以使用类似于“Canvas::::get_dimensions()来获取canvas的dimensions”。
实际上Canvas和ABC都impl了一个trait,暂且称之为“Item”。所以需要无差别的处理“T:Item”时,需要得到它的“dimensions”,这个“dimensions”只与“Item”的具体类型(如canvas)有关,而与“Item”具体类型的“Shape”(如这里的Circle)无关。如果每次调用时,都需要显式声明一个impl “Shape”的struct(虽然对于任意struct都获得相同的值),但是总感觉触犯了我的逻辑洁癖。除此之外应该没啥副作用了。
另外,如果使用trait const意味着要引入trait “Dimensions”,此时如果无差别的使用时,就需要“T:Item + Dimensions”。感觉上会变得更麻烦了。
PS:不过最感谢的是让我知道了还有“trait const”这个用法。我决定还是放弃了,但是trait const明显比一个trait function更符合这里的逻辑,所以可能准备改为“Canvas::::Dimensions”来获取吧。
PSS:其实,举例说明,这里的主要核心问题就是,我需要一类impl了trait “Item”的struct,我希望这些struct一定有dimensions这个property或者可以通过trait bound,使得我一定可以通过一个associate function 或者是 associate const来获取这个dimension。
--
👇
苦瓜小仔
当然,
Canvas::DIMENSIONS
的代价是:你必须引入 Dimension trait 和 WholePlane struct 到作用域。那么这涉及 trade-off:这种精简的写法是必须的吗。
我对这块也不是很熟练,但是我觉得有两个地方你可以考虑一下:
get_dimensions
方法不需要 self,所以可以考虑使用 Associated Constants;如果你想在方法上省略 shape 泛型,那么当某个 trait + 结构体泛型是唯一实现的时候,就可以做到。
非常感谢您的回答!做法很巧妙,但是我的例子举得简单了。我现在稍微改了下例子,实际上shape的实现非常多且复杂,而且impl在一个wrapper上没有意义。
PS:真实的程序比较复杂,我尽可能抽象出一个好理解,简单,但完整的逻辑做为例子,但之前应该没做好。
--
👇
苦瓜小仔