May 27, 2019
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
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