OOP has been the dominant paradigm for the past few decades. Despite the rise in functional languages this still remains the case. There is a fair amount of criticism that can be levelled at it. Personally I'm in a phase of rediscovery, having looked at both functional and procedural as alternatives, and finding myself drawn back to objects.
The first thing that springs to mind when talking about OOP is inheritance. This is perhaps the least useful facet. Outside of text books the problems that can genuinely be solved by it are not that common. Treating code as a taxonomy of is-a relationships is a good way to get into trouble, particularly on large projects. Composition is a much more flexible way to construct systems of objects; has-a trumps is-a.
Interfaces come up way more frequently than any other construct. The ability to define contracts of behaviour, albiet simple ones, is an invaluable tool. Objects can then take on many roles in a system depending on the context in which they are used.
Alan Kay believed message passing (in the form of method invocation) was at the heart of OOP. Code that reads well and is easy to understand, is usually code where great care has been taken to name things and design method signatures. Treating objects as black boxes you send a message to and get a result from allows you to hide complexity.
Related to this is encapsulation, the other great benefit of OOP code, though by no means is it exclusive to it. The ability to define a private implementation that is separate from an object's public interface is key to writing easily comprehensible code. The surface area of what you need to know about can be kept small in this way.
There's a lot of clever things you can do with OOP code, but I find it's the basic stuff outlined above that comes in most useful. The ability to hide implementation, accessible only via well defined messages on interfaces, makes OOP a useful paradigm.