V Fri, 28 Nov 2014 06:19:37 +0000 Uranuz via Digitalmars-d-learn <digitalmars-d-learn@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(); }