Ok, so I've spent the past few days ragging on various applications of object-oriented programming. So what do I consider OOP good for? Well the answer naturally depends on what you consider OOP to be. So before I attempt to ask "What is it good for?", I will prepare the way by looking at "What is Object Oriented Programming"?
The biggest problem with giving a definition for object-oriented programming is that there are so many to choose from. Worse, the vast majority consist of little more than vague handwaving giving little or no thought to the existence of non-OO techniques. Consider the list of features listed by Johnathan Rees on Paul Graham's site.
Consider the first example. Encapsulation is not a distinguishing feature of OOP. Not only is it common in numerous non-OO languages, but it is not supported by many OO languages including both Smalltalk and Python! Moreover encapsulation is a friendly name given to existentially quantified types, which are the underlying theory used to understand Modules. Ie. when you see a feature offering encapsulation, what you are really seeing is a module/package system (possibly in disguise). Yes that does mean that Java/C#/C++ classes are doing double duty as both a type definition AND a module system. Yes that is the cause of several problems you are probably experiencing. No it doesn't have to be that way, there are languages that successfully seperate the two orthoginal concepts.
I make use of theory here because it allows me to avoid handwaving. Specifically it allows me to avoid the trap of promoting specific language features to the status of paradigm definition just because they are favoured, or even common in OOP languages. Using this approach I can quickly eliminate Encapsulation, Protection, Ad hoc Polymorphism, Parametric Polymorphism, and Sum-of-Product-of-Function from Ree's list. This leaves us with only "Everything is an object", "All you can do is send a message", Specification Inheritance, and Implementation Inheritance to consider. So lets map these to theory and see what we have left:
- Everything is an object
- This is literally a meaningless phrase as either it is strictly a matter of syntax (2.add(3) vs. 2 + 3); or it is a matter of purity, at which point it begs the question.
- All You can do is send a message
- Message Passing. You can take your pick of various algebras and calculi to model this. CSP was popular for a while; Process Algebra has its admirers; but my favourate is the pi-calculus.
- Specification Inheritance
- This is subtype-polymorphism using subsumption.
- Implementation Inheritance
- Open Recursion. Not alot of use if you don't have subtype-polymorphism as well, and proves difficult to model when you do. The simplest treatments use a least-fixed-type operator applied to a 'self' abstraction.
Ultimately the above three concepts coalese into two conceptualisations of OOP.
The first focuses on the 'object', considering them as identifiable, autonomous, finite automatons communicating via message-passing. Conceptually we are talking about highly concurrent actor based models. This approach is the once taken by Simula, Erlang, Pick, and friends. However while it corresponds closest to the original conception of OOP, it is barely recognisable in modern mainstream OOP languages. In fact these languages are more likely to be described as concurrency-oriented than object-oriented.
The second focuses on the 'class', considering OOP in terms inheritance and subtyping. Conceptually we are talking about languages that provide records containing function typed attributes that are parametised by a recursive 'self' parameter that provides for 'late-binding'. The conventional way to model this theoretically is via Abardi and Cardelli's Object Calculus (or you could try one of the papers available online ie A Theory of Primitive Objects (second order systems) or An Imperative Object Calculus). Representitive languages include all the usual suspects: Java, C++, C#, Smalltalk, etc.
While concurrent agents with message passing might be the original definition of OO, as mentioned above most programmers who consider themselves OO wouldn't recognise this as OO; certainly almost none of the languages traditionally considered OO would fit this definition. So it is pointless to pursue it further. That leaves us with a single definition.
Object Oriented Programming is any programming based on a combination of subtype polymorphism and open recursion
Translated back into more common terms - programming based on a combination of
- Polymorphic functions that accept as actual parameters values of any subtype of their formal parameters, and
- Late binding, based on a distinguished 'self' parameter to functions that provides access to attributes of a record/object based on its runtime type.