We've now defined all three of the features required to make a language truly object-oriented:
(Programmer creation of) User-defined types
By way of review, let's summarize the benefits of each of these three language features.
Programmer creation of user-defined types
Provides an intuitive way to represent real-world objects, resulting in easier to verify requirements.
Classes are convenient units of reusable code, which means less code to write when building an application.
Through encapsulation, we minimize data redundancy—each item of data is stored once, in the object to which it belongs—and therefore lessen the chance of data integrity errors.
Through information hiding, we insulate our application against ripple effects if private details of a class must change after deployment, thereby dramatically reducing maintenance costs.
Objects are responsible for ensuring the integrity of their own data, making it easier to debug data integrity problems.
Can extend deployed code without having to change it, resulting in dramatically reduced maintenance costs.
Derived classes are much more succinct, which means less code overall to write/maintain.
Causes virtually no "ripple effects" on client code when new subclasses are invented, resulting in dramatically reduced maintenance costs.
A common misconception, held by many, is that switching from a non-OO to an OO programming language will dramatically speed up the development time of a given application. Anecdotes abound of managers who have expected that a team utilizing OO approaches should be able to craft an application in a fraction of the time that it would have taken them to build its non-OO counterpart—despite the fact that team in question might be utilizing object-oriented techniques for the first time ever!
Unfortunately, due to the learning curve involved in switching to the OO paradigm—particularly for software developers who've been entrenched in non-OOPL techniques for many years—it actually can take longer for a team to build its first OO application.
Where economies of scale do come into play, however, is during the maintenance stage of an application's life cycle. The maintenance stage of an application—OO or otherwise—is typically much longer/more costly than the development stage, and so by dramatically reducing ripple effects through the thoughtful use of encapsulation/information hiding and inheritance/overriding/polymorphism, we stand to reduce maintenance costs significantly.
Once we've become adept with the OO paradigm, we should indeed be able to shorten application development time, as well, by virtue of the fact that through reuse via inheritance, we'll have less code to write overall. And, in transitioning from one project to the next, if we embrace the philosophy of code sharing and reuse across projects, we can gain significant productivity during the development stage of the life cycle.