0

Disclaimer: I don't have a special knowledge about OOP, I tried to learn from other posts but it's not so clear for me.

So when I define a class, when to make an attribute protected and when to make it private. Do you have some rule of thumbs?

What confuses me is this principle of protected/private. If I don't need to access the attribute from outside the class, well, I simply won't access it (I mean, it's up to me!), I will access it only when I need. I feel like this private/protected attribute principle is like some protection against some metaphysical forces.

Joffrey L.
  • 175
  • 1
  • 7

2 Answers2

1

Some languages strictly prevent you from accessing private attributes, but Python (kind of for the reasons you've mentioned) doesn't do that.

As you said, "(I mean, it's up to me!)" - The only occasion this kind of protection is useful is when working with a team (or coming back to a project after a few months), and forgetting which attributes you're meant to be allowed to access from outside that class or not.

It is convention to prepend variables that are internal-only with a _, just to remind you to double check it's ok before referencing it from outside.

More info in docs.

Luke Storry
  • 6,032
  • 1
  • 9
  • 22
  • And if I change an attribute from public to "protected" using the underscore, do I need to define a property and a setter? – Joffrey L. Jul 25 '20 at 22:29
  • You don't ever really *need* to use properties or setters, they are optional extras that let you call a method as if it was an attribute. They are niceties for other components using your class, and as a private attribute isn't getting used by anything external, it doesn't make much sense to do for them either. – Luke Storry Jul 25 '20 at 22:47
  • If I need to tell team members that only access is allowed and not modification, what to do in this case? – Joffrey L. Jul 25 '20 at 23:07
  • Then use a @property or getter-method, pointing to an internal private variable – Luke Storry Jul 26 '20 at 01:22
0

A language like Java has strict protection against inappropriate access (but Python doesn't, as explained in other answers).

Java Example

Java's ArrayList is a good example of the use of private and protected members.

Looking at the linked source code, you will notice:

  • private int size; -- size is private because we don't want users fiddling with the size of the ArrayList directly. They are already able to add, remove, and clear the List, so the ArrayList class should maintain its own size from these methods. Allowing the user to manipulate size will only open the possibility of causing the size to be incorrect (and thus causing an inconsistent data structure). Note that the user has the public int size() method, so they are able to access the value of size at any time, but not assign a new value to it.
  • protected void removeRange(int fromIndex, int toIndex) -- This one is protected because there are already other ways of removing a range of elements from an ArrayList (specifically using arrayList.subList(fromIndex, toIndex).clear();, which eventually invokes ArrayList's removeRange method). Preventing unrelated classes from doing the same thing in multiple ways encourages cleaner and more consistent code - but to prevent redundancy, nested and child classes can still access these protected methods.

Python Example

While you can follow the same practices in Python, the language doesn't strictly prohibit access. Here is an example showing how you can still access protected and private members:

class MyClass(object):
    def __init__(self, x, y):
        self._x = x
        self.__y = y

s = MyClass(1, 3)
print(dir(s))
print(s._x)
print(s._MyClass__y)

Output:

['_MyClass__y', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_x']
1
3

As you can see, __y was detected as private and changed into _MyClass__y, and _x can still be accessed as _x, even though it's marked as protected with the underscore.

ELinda
  • 2,658
  • 1
  • 10
  • 9