Reputation: 8885
I try to get something more generic done but am failing on trying it with associated types. Given is a Shape
trait and a Renderer
type which tries to return a Builder
for a specific kind of shape.
shape
#[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;
}
builder
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
}
}
renderer
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
}
}
What I want to achieve is that the set_shape
method will return the RectangleBuilder
if the given shape
is of type Rectangle
Upvotes: 0
Views: 1839
Reputation: 65927
You need to provide a static method in the ShapeBuilder
trait that instantiates a new Self
. A static method is just a method with no self
parameter.
You can either add a method directly:
pub trait ShapeBuilder: Sized {
type Renderer: ShapeRenderer;
fn new() -> Self;
fn set_origin() -> Self::Renderer;
}
or be clever and define ShareBuilder
as a subtrait of Default
.
pub trait ShapeBuilder: Default {
type Renderer: ShapeRenderer;
fn set_origin() -> Self::Renderer;
}
Then, in set_shape
, you can instantiate the ShapeBuilder
:
impl <'a>Renderer<'a>{
pub fn set_shape<T: Shape>(&self, shape: T) -> T::Builder {
ShapeBuilder::new() // or Default::default()
}
}
Upvotes: 3