Passing reference data to class and incapsulation
Daniel Kozák via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Nov 28 02:03:10 PST 2014
V Fri, 28 Nov 2014 06:19:37 +0000
Uranuz via Digitalmars-d-learn <digitalmars-d-learn at puremagic.com>
napsáno:
> In D we a several data types which are passed by reference:
> dynamic arrays, associative arrays. And sometimes we need to pass
> these reference data to class instance to store it inside. One of
> the principles of object-oriented programming is incapsulation.
> So all class data should be only modyfiable via class methods and
> properties. But I we pass reference data to class (for example as
> parameter in constructor) we still can change these data from
> initial code and break some internal logic of class for modifying
> these data. Example:
>
> class Foo {
> this(int[] b) { bar = b; }
> private int[] bar;
> //Some methods
> }
>
> void main() {
> int[] bar = [1,2,3,4,5];
> Foo foo = new Foo(bar);
> //There I could do some logic with class
> bar[2] = 6; //I modify class without some checks from class
> //And there I might pass *bar* somewhere outside and break
> incapsulation
> }
>
> Same situation happens when I assign reference data to
> properties. I can check or do something with data at the moment
> of assignment, but I can't control that someone will modify using
> initial reference from outside. So do you copy reference data in
> constructors or properties? Should it be? Or call site should be
> responsible for not escaping reference somewhere outside and not
> modifying these data badly?
>
> There also possible some situations when these data should be
> shared between different pieces of code (for example different
> class instance could reference the same memory area). But I think
> this is not very good and safe approach and should be avoided if
> possible.
>
> But I think storing reference to class inside another class could
> be good approach because there could be different type of
> relations between classes. For plain data types we often have
> types of relations: *ownership* or *aggregation*. But classes can
> usualy have more types of relations: *usage* or when one class
> subscribes for events of another.
>
> Is there some good links to read for these questions that you
> could advice. After several hours of googling I haven't found
> good topics about these problems. And I have not enough time for
> reading big book.
You can wrap type and add suport for copy on write, something like this:
struct CoW(T:E[], E) {
T data;
bool change = false;
alias data this;
this(T v) {
data = v;
}
this(this) {
change = false;
}
void opIndexAssign(E v, size_t p)
{
if (change is false) {
data = data.dup;
change = true;
}
data[p] = v;
}
}
alias cowIntArr = CoW!(int[]);
class Foo {
this(cowIntArr b) { bar = b; }
private cowIntArr bar;
void printBar() {
writeln(bar);
}
}
void main(string[] args)
{
cowIntArr bar = [1,2,3,4,5];
auto foo = new Foo(bar);
bar[2] = 6;
writeln(bar);
foo.printBar();
}
More information about the Digitalmars-d-learn
mailing list