Firstly what is Polymorphism and why is it so important? Polymorphism is the ability to have a many implementations of
a behavior that conform to a single interface. Put in perhaps slightly better, pragmatic terms, you have one
implementations of a caller, that can operate on many implementations of a “parameter”, without conditionals, or
changing the callers code. For instance the following, pseudo?, Perl 6-ism method handler( $obj ) { $obj.execute() }
.
As you can imagine $obj
can be anything that has an execute method. For this Article I’ll give you two
implementations and one caller, in either Perl 5 or 6, or Java 7 or 8, boilerplate will be excluded for brevity.
Inheritance
Single Inheritance
Single inheritance is the most simple and well understood form of Polymorphism.
|
|
Multiple Inheritance
Multiple inheritance is often considered dangerous, is unavailable in Java and suffers from the The diamond problem. You should really only use this with a C3 MRO.
Flat Composition
Interfaces
Interfaces are probably the third most common form of Polymorhism, they are essentially codified contracts.
|
|
Traits
These are just the same as Interfaces in Java 8 you say? well yes, that’s what Java 8 calls them, Traits are a list of methods flattened into a class, but they cannot access state. This basically describes what Java 8 is doing, as you can’t access properties from within the interface, well.. at least not unless you do what I show here, which is basically access state through getters and setters.
|
|
Mixins
Mixins are basically traits that can access state, though some mixins (AFAIK Ruby) are implemented sneakily as multiple inheritance, rather than flat list composition. IMHO, Mixins should be implemented using flat list composition.
|
|
Typeless
Duck Typing
The has $!log
in the Mixin is actually a pretty good example of duck typing, we don’t check for debug we are just
calling it. Java is basically incapable of doing this, except, you can treat everything as an Object (if that’s all
you need).
Function References
references to functions may or may not be allowed to have varied signatures depending on the language, but so long as they have the same signature they are interchangeable, and thus polymorphic. So why aren’t normal functions (procedures), for example, Polymorphic, the problem with procedures is that you have to import the implementation from outside the file, where with polymorphic code, you can create your instance outside the file, pass it into code that’s in the file, without changing the code, pass in a different implementation, and it’ll continue to work. To modify procedural code, you’d have to modify at least the import, and in compiled code that means a rebuild. It’s worth noting these aren’t so much typeless as their is only one type to be concerned with, a function.
|
|
Miscellaneous
I’m personally skeptical of whether these actually fit the definition of Polymorphism, but they sort of do, just in completely different ways from the above.
Method Overloading
Method overloading is called ad hoc polymorphism and is kind of weird in that what it’s really doing is hiding the type change from the programmer. Reality is you’re kind of asking for different behavior, but you want to hide that it’s different in the caller. However since it means you wouldn’t have to change the caller, it counts.
|
|
Generics
I describe generics as class templates, because they remind me of having an HTML template, and then filling in the blanks by passing in variables, the variable happens to be a Type. Perl doesn’t have Generics, and I’m not aware of plans for it in Perl 6.
|
|
Reflection
Reflection is sort of polymorphic in that you can essentially treat all objects the same, via a single standard API.
I don’t know that I want to show the kind of Reflective code because it get’s real complicated fast, but for example,
@Inject
can be annotated in systems with CDI compliant injector, they will reflectivly treat all objects with this
the same, and then set the annotated property.