I have been reading Practical Object-Oriented Design in Ruby aka "POODR" by Sandi Metz. The book is coveted and frequently referenced as a beacon for establishing good software design habits. I just made it through chapter 5: "Reducing Costs with Duck Typing." POODR is very detailed and helpful; however, as a beginner I needed more examples to grasp the concept. I went on a journey through the internet and found endless resources that said "If it talks like a duck..", you know the rest. Once I had an 'aha' moment the phrase made more sense, but before that moment I was like:
Each resource was tangential to my goal of understanding duck typing, especially the hot debate between static and dynamic language users, y'all are serious. To get to the bottom of the duck typing concept, I have to start with some overarching concepts.
Sandi Metz wrote "..languages use the term "type" to describe the category of the contents of a variable...knowledge of the category of contents of a variable or its type allows an application to have an expectation about how those contents will behave."
Statically typed languages such as Java type-check before run time.
Basically static languages do some pre-flight checks before turning the human written code (source code) into code that the computer understands (machine code). This is advantageous because larger programs can run faster since all of the safety checks have been done. Another advantage is that visible type information can serve as documentation in the source code.
Dynamically typed languages such as Ruby type-check during runtime.
Dynamic languages are more spontaneous and take a laissez faire approach by type-checking when the code is being executed. No compiling and a more lax syntax are some advantages to using a dynamic programming language.
Need more info?
If you are still learning or need a refresher about the differences between dynamic and static languages here is an excellent resource.
Polymorphism translates to "many forms." In programming it is the ability of an object with different types to be handled by a common interface.
The concept of polymorphism is not a novel concept in programming. The concepts are referenced as early as
Carl Hewitt, Peter Bishop & Richard Steiger's proposal paper for A Universal Modular ACTOR Formalism for Artificial Intelligence in 1973.
"One way to build an ACTOR machine is to put each actor on a chip and build a decoding network so that each actor chip can address all the others."
Static Polymorphism aka compile time polymorphism in languages such as Java have interfaces that have special contracts on how to interact with other classes. One implementation of polymorphism is called method overloading which allows a class to have more than one method with the same name. Another implementation is called method overriding, which allows a method declaration in a sub class contained inside a parent class. Methods in static languages only work correctly if they know the classes and types of their arguments.
Dynamic Polymorphism aka runtime polymorphism in languages such as ruby refer to the ability of different objects to respond to the same message signature (method name and specified parameters). One example of dynamic polymorphism in an object oriented language is called "duck typing."
What is it?
Duck typing is a programming method that allows any object to be passed into a method that has the method signatures expected in order to run. In short, it's not important what an object is, rather what it does. Objects of different types can respond to the same messages as long as they have the specific method behavior. It solves the certain design qualms such as large cases statements and dot methods such as .is_a or .respond_to? that can potentially cause software rot. Essentially allowing your code to rely on public interfaces rather than object types allows for flexibility and change over time.
How does it work?
The implementation of the Cook class on the left is very rigid and resistant to change. The implementation on the right is an example of duck typing. The Cook class calls the method prepare_recipe and passes in the objects that allow each individual class to handle their own business logic. The classes don't have to keep track of another class's methods allowing for clean flexible interfaces.
Recently, I used duck typing to build better Rspec tests by stubbing out a fake console. Instead of relying on user input in the console I added a Console class and a FakeConsole class. Each class contained the same methods signatures so they would behave the same when testing the generate_primes method.
Alex Martelli summed it up well when he said "You don't really care for IS-A-- you really only care for Behaves-LIKE-A-- so, if you do test, this behavior is what you should be testing for."
If you stuck with me up to this point, thanks for reading. I have more topics to explore to reach full enlightenment, such as other implementations of polymorphism and statically typed language interfaces. Feel free to leave feedback or helpful comments 🙃 Cheers