jbaublitz / getset

Getters and Setters for Rust.
https://docs.rs/getset/
MIT License
338 stars 23 forks source link

Feature request: Getters and Setters that implement a Trait #91

Open CraigBuilds opened 1 year ago

CraigBuilds commented 1 year ago

It would be very useful if the getters and Setters could implement a trait fir the structure, instead of adding the implementation directly on the struct.

i.e for:

[derive(Getters)]

[getset(trait=GetXY)]

struct Foo { x: f32 y: f32 }

[derive(Getters)]

[getset(trait=GetXY)]

struct Bar { x: f32 y: f32 }

this would generate:

impl GetXY for Foo { fn x(&self) -> &f32 { &self.x } fn y(&self) -> &f32 { &self.y } }

impl GetXY for Bar { fn x(&self) -> &f32 { &self.x } fn y(&self) -> &f32 { &self.y } }

Instead of:

impl Foo { fn x(&self) -> &f32 { &self.x } fn y(&self) -> &f32 { &self.y } }

impl Bar { fn x(&self) -> &f32 { &self.x } fn y(&self) -> &f32 { &self.y } }

The attributes could also be field level. E.g

[derive(Getters)]

struct Bar {

[getset(trait=GetX)]

x: f32
y: f32

}

This would allow users to create some very powerful abstractions.

For example

fn move(pos: impl GetMutXY, vel: impl GetVelCopy, dt: f32) { pos.x() += vel.vx() dt; pos.y() += vel.vy() dt; }

This function will work with anything that has getmut getters for x and y, and getcopy getters for vx and vy.

You could create a dynamics library with functions that do not force the user to use a certain datastructure. They could derive the implementations for their own types and then use these functions freely.

This is a more generic solution compared to manually writing custom derives for the traits such as GetMutXY. If you have lots of traits like this, it would be infeasible to write a derive macro for all of them.

CraigBuilds commented 1 year ago

Since I cannot edit the description on my phone, I will add some extra information here:

One of the motivations for this is that rust does not have C++ like duck typing for generics. In C++, I could write:

void move(T obj, f32 dt) { obj.x += obj.vx dt; obj.y += obj.vy dt; }

And this could be called with any struct that has the fields x, vx, y, and vy.

Rust does not allow this because generics are type checked before they are momomorphized.