This is going to be a very non-technical, soft question and I am not sure if this is the right platform. But I am a beginning CS student so I hope you guys tolerate it.In the first semester we were introduced to OOP concepts like encapsulation, data hiding, modularity, inheritance and so on through Java and UML. (Java is my first programming language)The way I understand it, OOP is a way of managing software complexity. But its principles are not new or unique, they are in a sense universal to all engineering fields.For example a car is a very complex structure whose complexity is managed by a hierarchy of modular and encapsulated components with well-defined behaviors and interfaces.But I do not understand the reason behind introducing a new programming paradigm. I think all the principles used for managing complexity can be realized by procedural programming languages. For example, for modularity we can just divide the program into many small programs that perform well-defined tasks whose code is contained in separate files. These programs would interact with each other through their well-defined input and output. The files may be protected (encrypted?) to achieve encapsulation. For code re-use we can just call those files whenever they are needed in new programs. Doesn't this capture all what OOP is or am I missing something very obvious?I am not asking for a proof that OOP manages complexity. In my opinion it certainly does. But I think all the principles used to manage complexity like modularity, encapsulation, data hiding and so on can be very easily implemented by procedural languages. So why really OOP if we can manage complexity without it? 
Do we really need OO languages to manage software complexity?
object oriented design
Let me try with a really low theory answer :)What you are really asking is: Why include support for Object Orientation (OO) directly in the language when procedural languages can be used to design and write OO code?And the answer is: To have a standard for how OO is expressed in the source code so you don't end up with 22 different implementations for the same abstraction.For example, lets say I create a MagicButton and a MagicSlider which can be used in an user interface system. I need a way to group the methods which can be used with the MagicButton, the methods which can only be used with the MagicSlider, and the methods which can be used by both.  These objects share some methods because they are both Magic gui objects. I can do the grouping by naming functions in a special way MagicSlider_DoSomething ..., by including the methods in specific files named in a special way MagicSliderMethods.XXX, or I could find some other special way to do the same thing. If there is no standard way in the language to do it I will do it different from you, and differently from anyone else. This makes sharing code much more difficult.Yes, late dispatch  virtual methods in OO languages  can be implemented in procedural languages, but there are so many different ways to implement it. Depending on who wrote the code you will end up with different implementations of OO inside the same program.Think about the poor maintenance developer. This person must manage different object abstractions and different ways to call virtual methods depending on who wrote the original code.Also: Having the abstractions in the language allows advanced code editors such as Eclipse to do a lot of static analysis on the code. For example Eclipse can offer up a list of all methods which can be used on an object, as well as auto implementation of empty TODO methods.  Eclispe knows exactly which methods your class must implement based on which classes you extend and which interfaces you implement. This would be almost impossible if there were not a language standard to do OO.