Question

I understand the differences between them (at least in C#). I know the effects they have on the elements to which they are assigned. What I don't understand is why it is important to implement them - why not have everything Public?

The material I read on the subject usually goes on about how classes and methods shouldn't have unnecessary access to others, but I've yet to come across an example of why/how that would be a bad thing. It seems like a security thing, but I'm the programmer; I create the methods and define what they will (or will not) do. Why would I spend all the effort to write a function which tried to change a variable it shouldn't, or tried to read information in another class, if that would be bad?

I apologize if this is a dumb question. It's just something I ran into on the first articles I ever read on OOP, and I've never felt like it really clicked.

Was it helpful?

Solution

First, nothing in the language forces you to use access modifiers - you are free to make everything public in your class if you wish. However, there are some compelling reasons for using them. Here's my perspective.

  1. Hiding the internals of how your class operates allows you to protect that class from unintended uses. While you may be the creator of the class, in many cases you will not be the only consumer - or even maintainer. Hiding internal state protects the class for people who may not understand its workings as well as you. Making everything public creates the temptation to "tweak" the internal state or internal behavior when the class isn't acting the way you may want - rather than actually correcting the public interface of internal implementation. This is the road to ruin.

  2. Hiding internals helps to de-clutter the namespace, and allows tools like Intellisense to display only the relevant and meaningful methods/properties/fields. Don't discount tools like Intellisense - they are a powerful means for developers to quickly identify what they can do with your class.

  3. Hiding internals allows you to structure an interface appropriate for the problem the class is solving. Exposing all of the internals (which often substantially outnumber the exposed interface) makes it hard to later understand what the class is trying to solve.

  4. Hiding internals allows you to focus your testing on the appropriate portion - the public interface. When all methods/properties of a class are public, the number of permutations you must potentially test increases significantly - since any particular call path becomes possible.

  5. Hiding internals helps you control (enforce) the call paths through your class. This makes it easier to ensure that your consumers understand what your class can be asked to do - and when. Typically, there are only a few paths through your code that are meaningful and useful. Allowing a consumer to take any path makes it more likely that they will not get meaningful results - and will interpret that as your code being buggy. Limiting how your consumers can use your class actually frees them to use it correctly.

  6. Hiding the internal implementation frees you to change it with the knowledge that it will not adversely impact consumers of your class - so long as your public interface remains unchanged. If you decide to use a dictionary rather than a list internally - no one should care. But if you made all the internals of your class available, someone could write code that depends on the fact that your internally use a list. Imagine having to change all of the consumers when you want to change such choices about your implementation. The golden rule is: consumers of a class should not care how the class does what it does.

OTHER TIPS

I'm the programmer is a correct assumption only if you're the only programmer.

In many cases, other programmers work with the first programmer's code. They use it in ways he didn't intend by fiddling with the values of fields they shouldn't, and they create a hack that works, but breaks when the producer of the original code changes it.

OOP is about creating libraries with well-defined contracts. If all your variables are public and accessible to others, then the "contract" theoretically includes every field in the object (and its sub-objects), so it becomes much harder to build a new, different implementation that still honors the original contract.

Also, the more "moving parts" of your object are exposed, the easier it is for a user of your class to manipulate it incorrectly.


You probably don't need this, but here's an example I consider amusing:

Say you sell a car with no hood over the engine compartment. Come nighttime, the driver turns on the lights. He gets to his destination, gets out of the car and then remembers he left the light on. He's too lazy to unlock the car's door, so he pulls the wire to the lights out from where it's attached to the battery. This works fine - the light is out. However, because he didn't use the intended mechanism, he finds himself with a problem next time he's driving in the dark.

Living in the USA (go ahead, downvote me!), he refuses to take responsibility for his incorrect use of the car's innards, and sues you, the manufacturer for creating a product that's unsafe to drive in the dark because the lights can't be reliably turned on after having been turned off.

This is why all cars have hoods over their engine compartments :)


A more serious example: You create a Fraction class, with a numerator and denominator field and a bunch of methods to manipulate fractions. Your constructor doesn't let its caller create a fraction with a 0 denominator, but since your fields are public, it's easy for a user to set the denominator of an existing (valid) fraction to 0, and hilarity ensues.

It is primarily a hiding and sharing thing. You may produce and use all your own code, but other people provide libraries, etc. to be used more widely.

Making things non-public allows you to explicitly define the external interface of your class. The non-public stuff is not part of the external interface, which means you can change anything you want internally without affecting anyone using the external interface,

You only want to expose the API and keep everything else hidden. Why? Ok lets assume you want to make an awesome Matrix library so you make

class Matrix {
   public Object[][] data //data your matrix storages
   ...
   public Object[] getRow()
}

By default any other programmer that use your library will want to maximize the speed of his program by tapping into the underlying structure.

//Someone else's function
Object one() {data[0][0]}

Now, you discover that using list to emulate the matrix will increase performance so you change data from

Object[][] data => Object[] data

causes Object one() to break. In other words by changing your implementation you broke backward compatibility :-(

By encapsulating you divide internal implementation from external interface (achieved with a private modifier). That way you can change implementation as much as possible without breaking backward compatibility :D Profit!!!

Of course if you are the only programmer that is ever going to modify or use that class you might as well as keep it public.

Note: There are other major benefits for encapsulating your stuff, this is just one of many. See Encapsulation for more details

I think the best reason for this is to provide layers of abstraction on your code.

As your application grows, you will need to have your objects interacting with other objects. Having publicly modifiable fields makes it harder to wrap your head around your entire application.

Limiting what you make public on your classes makes it easier to abstract your design so you can understand each layer of your code.

For some classes, it may seem ridiculous to have private members, with a bunch of methods that just set and get those values. The reason for it is that let's say you have a class where the members are public and directly accessible:

class A 
{
    public int i;

   ....
}

And now you go on using that in a bunch of code you wrote. Now after writing a bunch of code that directly accesses i and now you realize that i should have some constraints on it, like i should always be >= 0 and less than 100 (for argument's sake). Now, you could go through all of your code where you used i and check for this constraint, but you could just add a public setI method that would do it for you:

class A
{
    private int i;
    public int I 
    {
        get {return i;}
        set 
        {
            if (value >= 0 && value < 100)
                i = value;
            else
                throw some exception...
         }
    }
}

This hides all of that error checking. While the example is trite, situations like these come up quite often.

It is not related to security at all.

Access modifers and scope are all about structure, layers, organization, and communication.

If you are the only programmer, it is probably fine until you have so much code even you can't remember. At that point, it's just like a team environment - the access modifiers and the structure of the code guide you to stay within the architecture.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top