Encapsulation
I wonder how to solve the problem of encapsulation in aggregated objects.
Example:
public class CustomModel : ICloneable
{
private int _age;
public int Age
{
get { return this._age;}
set { this._age=value;}
}
public override object Clone()
{
return this.MemberwiseClone();
}
}
public class SafeClass
{
private CustomModel _model;
public SafeClass(CustomModel model)
{
// version 1
this._model = model;
// version 2
this._model = (CustomModel)model.Clone();
}
}
Now if we write the constractor code in version 1, then create an instance of SafeClass:
CustomModel cm = new CustomModel();
cm.Age = 20;
SafeClass sc = new SafeClass(cm);
cm.Age = 40; //==> here, we can temper with internal data of sc object ! It lacks encapsulation !
It is possible to modify internals of SafeClass from outside. We can simply solve the problem:
SafeClas sc = new SafeClass((CustomModel)cm.Clone());
But we can assume, that developer using our SafeClass forget to clone the cm object before passing it to the constructor. In such situation SafeClass would be vulnerable to modification internals from outside.
If we decided to clone CustomModel in constructor of SafeClass (version 2), our class would be safe.
What if client of SafeClass is aware of risk related to passing references to other objects.
Let's assume he don't know the code of SafeClass(he don't have to) and intentionally clone the parameter of SafeClass constructor (as shown above). In that way, CustomModel would be cloned twice.
What do you think about that ?
What are the best practices for encapsulation in such situation ?
Regards
Jan MontanoPosted Aug 23, 2009, 10:18 PM
// I agree with your line below and this will solve the problem. This is also the basic way to do it.
SafeClas sc = new SafeClass((CustomModel)cm.Clone());
"But we can assume, that developer using our SafeClass forget to clone the cm object before passing it to the constructor. In such situation SafeClass would be vulnerable to modification internals from outside."
We must not create a library based on the skill level of it's user. It will just create a very complicated code.
The developer must know and not forget. It's his job. Initially, a developer must know what a string is and what an integer is. Consequently, he must also know what a reference type is and what a value type is.
The Clone is there for a purpose. It's the developer's responsibility to know what its purpose is.