Encapsulating field

Maciej Poleski d82ks8djf82msd83hf8sc02lqb5gh5 at gmail.com
Fri Jul 10 19:16:59 UTC 2015


Hi

I'm still working on change signature refactoring (which turned out to be very boring task consisting of hundreds of LOC only to gather data from user...).

But I was thinking about other refactorings as well and wanted to share my thoughts about encapsulating fields.
What does it mean to encapsulate field? In general I say that field is accessible if we can get its address (memory location in which it resides). Encapsulating is about removing this possibility with respect to given field and modifying existing code to adapt to this change.

In languages like Java it is very common to have methods like getX() and setX(...). getX() return reference to our field. And we have our address... In Java there is no const specifier. By such change we lose only possibility to assign new object reference to given field. This is "fixed" using setX(...) method which does exactly this job.

In C++ things are more complicated. If we generate getter and setter as above, we will not "restore" capabilities:

class X {
    void f();
};

class A {
    X x;
public:
    const X& getX() const { return x; }
    void setX(const X &x) { this->x=x; }
};

Basically get method will allow to use field x in all non-mutating context (and in all contexts in which there is implicit lvalue to rvalue cast). These uses should not breach our invariants. set method will handle exactly one kind of mutating operation: assignment (using operator=). We will be unable to call f() on this field (because f() is not const). Similarly other actions may be no longer possible.
If we decide to return non-const reference in get method - we will have full access to the object (which means it is not encapsulated). If we return a copy - that's not necessary expected side effect. Not to mention that "changes" to this new object would be fianlly lost.

In languages which force accesses to objects through references what we protect by get/set is in fact only that reference. Object is as accessible as before. That's what makes this a bit more complicated.

Encapsulation in this form will break all use cases for which there is no appropriate set-method generated.


The question is if we care about this (such use cases in fact violate encapsulation), or has anybody different idea of approach to this refactoring?


More information about the KDevelop-devel mailing list