Search code examples
c#oopencapsulation

How to get all the functionality of a type without exposing it to the client?


I just got in trouble from a teacher and I'm a little confused.

I have data that is stored in a VectorWithTops class like this

public class VectorWithTops<T>
{
    private readonly Dictionary<T, int> TopsWithIndices = 
       new Dictionary<T, int>();
    private readonly Vector<double> _data;

    public VectorWithTops(
       List<T> topHeaders,
       Vector<double> data)
       {
           // set TopsWithIndices to be topHeaders and index in vector
           // ...

           _data = data
       }

    // method to get value in vector at certain topHeader index
    // ...
}

The whole purpose of this class is to be able to access a vector index by it's respective header of type T. The vector itself is not exposed to the client however.

Now I have a different class in which I am using a VectorWithTops, and in order to perform a bunch of operations on my vector I decided to expose _data in a public method, then directly operate on the matrix. I figured this was fine because _data is private readonly so it's not going to be able to be changed anyways.

My teacher sort of lost his mind at this, and told me what I should have done is add the operators to my VectorWithTops class for instance

static Vector<double> operator *(VectorWithTops<T> leftSide, Vector<double> rightSide)
{
    return leftSide._data*rightSide;
}

Then I can use this static method without exposing the actual vector to the client. My question is then how is this encapsulation going to work if I require a great deal of the operator methods for my vector, or a matrix even? Would I have to rewrite all of these static methods in my own class so that the data is ensured to be operated on inside my class? I understand my teacher's complaint about the vector in my case being exposed, but how am I supposed to freely operate on my vector inside VectorWithTops then?


Solution

  • In this case Vector<T> is an immutable type which isn't even passed by reference. Provided that your field definition remains readonly, there's no danger in exposing it. It cannot be changed by another object without using reflection hacks.

    You could make the argument that the Vector<T> is an implementation-specific detail that might change in a future, and that consumers of your VectorsWithTops<T> class should not rely on that field remaining the same. But unless you're a masochist I wouldn't go any further than just adding a public getter/property for the Vector<T>. If at some point you need to change your private field to another data structure, the public property could be modified at that time to perform a conversion.

    On the other hand, sometimes you just gotta do what the teacher wants to pass the class...