I am writing a class which basically is a wrapper around a dictionary with some extra functionality. This dictionary is stored as protected member _store. Now I am writing a __eq__ method to compare objects of my class. The criterion is, if the underlying dictionaries are equal, the objects are equal, therefore the easiest approach would be:

def __eq__(self, other):
    return self._store == other._store

But this entails accessing the protected members of a third object. Although this third object belongs to the same class as self. Can we consider this breaking encapsulation??

The other option is to do an item comparison between the two objects, which leads to a slightly less efficient and longer code (keys set comparison and check that the key-value pairs of one object equal the ones of the other object).

  • Whether encapsulation should apply to the class or to the instance is disputed. Many implementations imply the former, and many theoreticians prefer the latter. There is no consensus 'true answer'. Dec 13 '14 at 10:30
  • @KilianFoth: That's basically the difference between Abstract Data Types and Objects. I find it interesting that you put Haskell (which uses ADTs) in the pragmatic camp and Java (which uses Objects) in the theoreticians camp, though :-D Dec 13 '14 at 16:04

Since you tagged this with , I'll give you the Python perspective on this.

In Python, this is entirely normal. Attributes are not private, they are merely marked as 'internal', by convention, by using a leading underscore. So _store is something that is 'internal' to the class, just as the implementation of __eq__ is an internal matter.

You are not breaking encapsulation here; you are merely providing a correct implementation of a hook method. Accessing other._store here is no different from accessing self._store in that respect. That's because Python is a pragmatic language, it is not a purist OO language (you can use functional and procedural paradigms whenever you feel that fits the problem space better, for example).

Note that you may want to return the NotImplemented singleton object for comparisons that your class doesn't support:

def __eq__(self, other):
    if not isinstance(other, MyClass):  # or not hasattr(other, '_store') perhaps
        return NotImplemented
    return self._store == other._store

Python would then delegate the test to the other object; if it doesn't implement the __eq__ method or returns NotImplemented as well, then Python falls back to an identity test (self is other).

You'll find this pattern (using internal attributes in comparison hook methods) throughout the Python standard library. For example, all comparison methods for the decimal.Decimal() class delegate to the Decimal._cmp() method, and the implementation for that method is based almost exclusively on using internal attributes and methods (_is_special, _isinfinity(), _sign, _exp and _int), accessed both on self and other.

Some more examples:


You tagged this with , so the answer is: no. The fact that objects only know about their own private implementation / representation and not about that of other objects even of the same type is the defining characteristic of object-oriented data abstraction as opposed to Abstract Data Types, where instances of an ADT do know about the private implementation of other instances of the same type.

If you are familiar with Java, then there is a simple way to think about this: class == ADT, interface == object.

This is beautifully explained in On Understanding Data Abstraction, Revisited by William R. Cook.

Note that there's nothing wrong with ADTs per se, but a) as the name implies they rely on types (in the type-theoretic sense of the word, by which they mean static types), which Python doesn't have, and b) you specifically tagged the question with .

Note also that it is not quite easy to define what "two ADT instances of the same type" means in Python, since, after all, classes aren't types, ducks are.

  • 2
    You seem to imply that there is a well-defined, generally agreed-up solid definition of what "object-oriented" actually means... ;) Dec 13 '14 at 12:47
  • @FredOverflow: I'm implying that there is a somewhat "sane" definition of "object-oriented data abstraction", which is only a small part of OO. Dec 13 '14 at 12:56
  • @FredOverflow: let me clarify. I am only talking about data abstraction here, not overall system design. And "sane" was a misnomer, I meant "useful". A definition of object-oriented data abstraction that is identical to the definition of an Abstract Data Type is useless, because the two are clearly different. Realizing this was the brilliance of Simula, and not understanding that Simula actually had invented an entirely new abstraction mechanism and not just a nice way of writing ADTs, is the bane of languages like C++, Java and C#. Dec 13 '14 at 16:07
  • I've heard people say that focusing too much on Alan Kay's interpretation of OO doesn't give enough credit to Dahl and Nygaard. But actually, by pretending that Objects are basically just ADTs with different syntax, you are basically implying that Dahl and Nygaard didn't invent anything. How's that for not giving credit? Alan Kay OTOH says that Dahl and Nygaard were brilliant, but everybody ignored their brilliance and didn't realize that they had actually invented something profoundly new. (Well … everybody except the guys at Xerox, obviously … he's not that modest :-D ) Dec 13 '14 at 16:11
  • Saying that the class-based approach to object-orientation is equivalent to a different syntax for declaring Abstract Data Types is an overly reductionist argument, which entirely ignores the fact that inheritance (whether you use implementation inheritance or type inheritance) makes a significant difference in the capabilities of the two paradigms. Inheritance is the defining factor of object-orientation, not encapsulation.
    – Jules
    Dec 13 '14 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.