Action at a distance, separating operations from subjects
Eric
geachte.eric at gmail.com
Mon Jul 30 16:42:52 UTC 2018
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;
}
More information about the Digitalmars-d-learn
mailing list