www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Adding a payload to a type

reply Amex <Amex gmail.com> writes:
I have some types I've declared and I'd like to magically extend 
them and add data. The problem is I inheriting from them them is 
bad news.

Suppose, for example, I have an image type that is used in an 
application. For a small part of the application it needs to 
associate with each image type an xy coordinate type that adds a 
coordinate to the image to be used by the part of the app that 
needs to have coordinates for the image. The rest of the app does 
not care or need the xy coordinates.

Inheritance solves this problem in some sense except it doesn't. 
If I want to add new data then it breaks.

class image;
class xy : image; // can only add an image.
class z : ??; ?? could be xy, image, or something else

Inheritance is not the correct thing to do here. I only want to 
associate data with an object. The hierarchy does not matter.


I could add a payload type to image but this causes problems 
since it would have to be void or of a singular type. Mainly it 
causes problems with the serializer I'm using since it can't 
handle voids(I might be able to get it to work with a special 
type but it will not be easy).


I could, of course, add a parallel struct that somehow associates 
the image it's extra data but to keep them in sync will not be 
easy since it will have to persist between runs(so the address 
could not be used).

One could think of what I'm trying to do is create a tuple that 
holds the image and any other data.

tuple(tuple(image, xy), z) // the outer tuple may occur later 
without knowing that the image has been "wrapped".

How does one normally handle this? It seems like something really 
simple to do(attach data) but it has no real programmatic way to 
do naturally that works with oop.


The main thing is that attaching different data should "stack" 
and not effect the base type or break the type hierarchy. If 
something takes an image it should take any extended object.


I feel like the only way to do this is to create a special type 
that can be serialized properly and is part of the base class... 
I'll have to do it for all the classes. Hopefully someone has 
some better ideas?
May 27 2019
parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 27 May 2019 at 08:40:45 UTC, Amex wrote:
 I have some types I've declared and I'd like to magically 
 extend them and add data. The problem is I inheriting from them 
 them is bad news.

 Suppose, for example, I have an image type that is used in an 
 application. For a small part of the application it needs to 
 associate with each image type an xy coordinate type that adds 
 a coordinate to the image to be used by the part of the app 
 that needs to have coordinates for the image. The rest of the 
 app does not care or need the xy coordinates.

 Inheritance solves this problem in some sense except it 
 doesn't. If I want to add new data then it breaks.

 class image;
 class xy : image; // can only add an image.
 class z : ??; ?? could be xy, image, or something else

 Inheritance is not the correct thing to do here. I only want to 
 associate data with an object. The hierarchy does not matter.


 I could add a payload type to image but this causes problems 
 since it would have to be void or of a singular type. Mainly it 
 causes problems with the serializer I'm using since it can't 
 handle voids(I might be able to get it to work with a special 
 type but it will not be easy).


 I could, of course, add a parallel struct that somehow 
 associates the image it's extra data but to keep them in sync 
 will not be easy since it will have to persist between runs(so 
 the address could not be used).

 One could think of what I'm trying to do is create a tuple that 
 holds the image and any other data.

 tuple(tuple(image, xy), z) // the outer tuple may occur later 
 without knowing that the image has been "wrapped".

 How does one normally handle this? It seems like something 
 really simple to do(attach data) but it has no real 
 programmatic way to do naturally that works with oop.


 The main thing is that attaching different data should "stack" 
 and not effect the base type or break the type hierarchy. If 
 something takes an image it should take any extended object.


 I feel like the only way to do this is to create a special type 
 that can be serialized properly and is part of the base 
 class... I'll have to do it for all the classes. Hopefully 
 someone has some better ideas?
There's of course many different ways to skin a cat. Here's my first idea: class Image { // regular image stuff Metadata[] metadata; T getMetadata(T : Metadata)() { foreach (e; metadata) { if (cast(T)e !is null) { return cast(T)e; } } return null; } } abstract class Metadata {} class Coordinates : Metadata { int x, y; this(int x, int y) { this.x = x; this.y = y; } } unittest { auto img = new Image(); img.metadata ~= new Coordinates(1,2); auto coords = img.getMetadata!Coordinates; assert(coords.x == 1); assert(coords.y == 2); } This could easily be extended to support multiple metadata of the same type by adding a name field or such. -- Simen
May 27 2019