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