how do the four main oop principles (inheritance, encapsulation, abstraction, and polymorphism) work together to make a well-designed application? how do they allow a programmer to create more reusable and maintainable code?