2016-09-07 4 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 
    } 
} 

То, что я хочу достигнуть, т шляпа метод set_shape вернет RectangleBuilderесли данный shape имеет тип Rectangle

+0

ли строители нужны параметры, чтобы инициализировать новый экземпляр, или они должны быть конструктивны без параметров? –

+0

на самом деле да - бит - это какая-то реализация заглушки - сначала нужно добиться перехода от рендерера к возвращающему строителю. Возможно, вы уже поняли, что я пытаюсь создать шаблон строителя здесь. – xetra11

+0

Я думаю, что не правильно сформулировал свой первый комментарий. Чтобы построить строитель, нужны ли вам параметры или должна ли каждая реализация поддержки ShapeBuilder поддерживать без параметров? –

ответ

2

Вам необходимо предоставить статический метод в ShapeBuilder признака, который создает новый Self. Статический метод - это просто метод без параметра self.

Вы можете добавить метод непосредственно:

pub trait ShapeBuilder: Sized { 
    type Renderer: ShapeRenderer; 

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

или быть умным и определить ShareBuilder как subtrait из Default.

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 :: ShapeBuilder» (это неправильный синтаксис, который я знаю) – xetra11

+0

@ xetra11 Да. 'Self' в определении определения означает« конкретный тип, который реализует эту черту ». В этом случае 'RectangleBuilder'. Вы можете также написать 'T :: Builder :: new()' или ' :: new()' вместо просто 'ShapeBuilder :: new()', если это более понятно для вас. – krdln

+0

Ah okay ... так неявно он знает, что я говорю о ассоциированном типе 'T', если я назову' ShapeBuilder :: new() '- довольно много магии и очень плохой читаемости, вы так не думаете ? – xetra11

Смежные вопросы