2016-09-07 80 views
0

我尝试获得更通用的东西,但是在尝试使用关联类型时失败。鉴于是Shape特质和Renderer类型,它试图返回一个Builder为特定类型的形状。通过关联类型返回泛型类型

形状

#[derive(Clone, Copy)] 
pub struct Rectangle{ 
    pub origin: Point, 
    pub height: usize, 
    pub width: usize, 
} 

pub trait Shape{ 
    type Builder : ShapeBuilder; 
} 

impl Shape for Rectangle{ 
    type Builder = RectangleBuilder; 
} 

建设者

pub trait ShapeBuilder{ 
    type Renderer: ShapeRenderer; 
    fn set_origin() -> Self::Renderer; 
} 

pub struct RectangleBuilder; 

impl ShapeBuilder for RectangleBuilder{ 
    type Renderer = RectangleRenderer; 
    fn set_origin() -> Self::Renderer{ 
     RectangleRenderer 
    } 
} 

渲染

pub struct Renderer<'a>{ 
    canvas:&'a mut Canvas 
} 

impl <'a>Renderer<'a>{ 
    pub fn new(canvas:&'a mut Canvas) -> Renderer { 
     Renderer{ 
      canvas: canvas 
     } 
    } 
    pub fn set_shape<T: Shape>(&self, shape: T) -> T::Builder{ 
     // trying to return the specific builder through shape::Builder 
     // or something like that 
    } 
} 

我想实现为t帽子set_shape方法将返回RectangleBuilder如果给定shape的类型为Rectangle

+0

执行建设者需要以初始化一个新的实例参数,或者他们应该是不带参数constructible? –

+0

实际上是 - 位是某种存根实现 - 首先要实现从呈现器到返回的构建器的转换。您可能已经意识到我尝试在此创建构建器模式。 – xetra11

+0

我想我没有正确说出我的第一条评论。为了构建一个构建器,你是否需要参数,或者每个ShapeBuilder的实现都必须支持没有参数的构造? –

回答

2

您需要提供在ShapeBuilder特质实例化一个新的Self一个静态方法。静态方法只是一个没有self参数的方法。

您可以直接添加的方法:

pub trait ShapeBuilder: Sized { 
    type Renderer: ShapeRenderer; 

    fn new() -> Self; 
    fn set_origin() -> Self::Renderer; 
} 

或聪明并定义ShareBuilder作为Default一个subtrait。

pub trait ShapeBuilder: Default { 
    type Renderer: ShapeRenderer; 

    fn set_origin() -> Self::Renderer; 
} 

然后,在set_shape,你可以实例化ShapeBuilder

impl <'a>Renderer<'a>{ 
    pub fn set_shape<T: Shape>(&self, shape: T) -> T::Builder { 
     ShapeBuilder::new() // or Default::default() 
    } 
} 
+0

在此示例中。将'Rectangle'对象设置为'shape'参数时 - 将会使用'ShapeBuilder :: new()'返回一个RectangleBuilder?因为我不明白如果返回的Builder是一个'RectangleBuilder',它只是返回'Self',而不是像'Self :: ShapeBuilder'(这是我知道的错误语法) – xetra11

+0

@ xetra11是如何解决的。特质定义中的“自我”意味着“实现这种特质的具体类型”。在这种情况下,'RectangleBuilder'。如果你更清楚,你也可以编写'T :: Builder :: new()'或' :: new()'而不是'ShapeBuilder :: new()'。 – krdln

+0

啊好吧......如果我调用ShapeBuilder :: new(),那么它隐含地知道我正在谈论相关的'T'类型 - 非常神奇并且可读性很差,你也不这么认为? – xetra11