www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Action at a distance, separating operations from subjects

Not a question.

I came up with a nice and simple way to apply operations on an 
arbitrary number of members of unknown type of a set of objects 
of unknown type. This without having to reimplement these 
operations for each class that needs to support the operation(s). 
All this without explicitly storing references to these members. 
The only requirement is that the members fulfill the expectations 
of the operations.

An example will make it clearer.


// First we need to store the operations somewhere:
class Storage {
     Operations operations;
}


// And here we have a subject that contains data structs (of any 
type) that we want to apply the operations on.
// There may also be a SubjectB, C, ...
// For simplicity it subclasses Storage but operations could also 
be stored externaly, e.g in an array, or in some cases in the 
subject itself.

class SubjectA : Storage {

     // The members we want operations to work on.
     // Their type doesn't matter as long as they are compatible 
with
     // the operations. In this example assume these have a name 
and value member
     SomeStruct1 a;
     SomeStruct2 b;
     SomeStruct3!Y c;

     // Make these members available for operations with one line:
     this() {
         operations.operateOn(a, b, c);
     }
}


// After this simple setup you can now apply operations from 
anywhere and whenever you want:
foreach(Storage stor; storageList) {
     string s = stor.operations.concatNames();  // concats the 
names of a b c
     stor.operations.setValue(s);               // sets the value 
of a b c
}


The advantage of this is that you can have SubjectB, SubjectC, 
... all with different kind of members, and it only takes one 
line to make them available for the operations. Also, the 
subjects do not need to know how many operation there are and 
what these operations do with the members a,b,c.


// Here is how to define the operations:

struct Operations {

   void operateOn(T...)(ref T ts) {
       concatNames = {
           string name;
           foreach(ref t; ts) name = name ~ t.name;
           return name;
       };

       setValue = (string val) => {
           foreach(ref t; ts) t.value = val;
       };

     }

     string delegate() concatNames;
     void delegate(string s) setValue;
}
Jul 30 2018