In short: The same as just “programming,” using different features (notably OO and generic styles) in combination as needed.
Back when having OO and generic programming in the same language was still new, “multiparadigm programming” was originally a fancy way of saying “programming using more than one programming style, each to its best effect.” For example, using object-oriented programming when run-time resolution between different object types is required and generic programming when static type safety and run-time performance is at a premium. Naturally, the main strength of multiparadigm programming is in programs where more than one paradigm (programming style) is used, so that it would be hard to get the same effect by composing a system out of parts written in languages supporting different paradigms. The most compelling cases for multiparadigm programming are found where techniques from different paradigms are used in close collaboration to write code that is more elegant and more maintainable than would be possible within a single paradigm. A simple example is the traversal of a statically typed container of objects of a polymorphic type:Here,
Shape will be an abstract base class defining the
interface to a hierarchy of geometric shapes. This example easily
generalizes to any standard library container:
Is this OOP, GP, functional, or conventional structured programming? All of the above: It’s a function template (GP) with a procedural body (conventional structured) that uses a generic algorithm (GP again) and a lambda (functional) that takes a pointer to a base class and invokes a virtual function (OO). The key point is that this is all just “programming.”
So today instead of “multiparadigm programming” we should simply say “programming.” It’s all programming, just using the right language features together in combination as usual.