Duck typing is a style of dynamic typing in programming. In this style, the valid semantics of an object are determined not by inheriting from a particular class or implementing a particular interface, but by the “current collection of methods and attributes.” The concept takes its name from the duck test, developed by James Whitcomb Riley, which can be expressed as follows:

“A bird can be called a duck when it is seen to walk like a duck, swim like a duck and quack like a duck.”

Start with the problem: we are using inheritance to provide the behavior of a class, which causes some problems.

Such as:

1. Code repeats in multiple subclasses

2. Runtime behavior is not easy to change

3. It is difficult to know all the behavior of the class being implemented.

4. Changing the parent class will cause a general effect on other subclasses.

This means that whenever you need to change a behavior, you have to track it down and change it in every class that defines it, which can lead to new errors!

This leads to one of the design principles in the book Head-First Design Patterns:

Identify changes that may need to be made in your application and isolate them from code that doesn’t need to be changed.

In this way, code changes cause fewer unintended consequences and the system becomes more resilient.

The following uses javascript to implement the duck type (polymorphic)

var duck = {
    duckSinging: function(){
	console.log( 'Quack quack'); }};var chicken = {
    duckSinging: function(){
	console.log( 'Quack quack'); }};var choir = [];  / / the choir

var joinChoir = function(animal) {
  if (animal && typeof animal.duckSinging === 'functioin') {
    choir.push(animal);
    console.log('Congratulations on joining the glee Club.');
    console.log('Number of choir members :'+ choir.length); }}; joinChoir(duck);// Congratulations on joining the choir
joinChoir(chicken); // Congratulations on joining the choir
Copy the code

In the duck type, the focus is on the behavior of the object, what it can do; Instead of focusing on the type the object belongs to. In the code above, chicken joined the chorus with the behavior of duckSinging.

Duck types typically benefit from “not” testing methods and the types of arguments in functions, relying instead on documentation, clear code, and testing to ensure proper use.

In a normal type, whether we can use an object in a particular scenario depends on the type of the object, and in a duck type, it depends on whether the object has a certain property or method — that is, if it has a certain property or method that passes the duck test, it can be used.

Examples from the book javaScript Design Patterns and Development Practices:

Let’s say we want to write a map application, and now we have two alternative map API providers to access our application. So far we have chosen Google Maps, and the Google Maps API provides the Show method, which is responsible for displaying the entire map on the page. Example code is as follows:

var googleMap = {
  show: function() {
    console.log('Start rendering Google Maps')}}var renderMap = {
  googleMap.show();
}

renderMap(); // Start rendering Google Maps
Copy the code

Later, when we want to change Google Maps to Baidu maps or other maps for some reason, we can abstract out the same part of the program (the map part) and rewrite the renderMap function.

var googleMap = { 
  show: function(){
		console.log( 'Start rendering Google Maps'); }};var baiduMap = { 
  show: function(){
		console.log( 'Start rendering baidu Map'); }};var renderMap = function( map ){
	if ( map.show instanceof Function){ map.show(); }}; renderMap( googleMap );// Output: Start rendering Google Maps
renderMap( baiduMap ); // Output: Start rendering Baidu map
Copy the code

When we send the message of “show map” to Google map object and Baidu map object respectively, their show method will be called respectively, which will produce different execution results. The polymorphism of the object indicates that the “what” and “how” can be separated, and even if the search map is added later, the renderMap function does not need to be changed at all.

var sosoMap = { 
  show: function(){
		console.log( 'Start rendering search map'); }}; renderMap( sosoMap );// Output: start rendering search map
Copy the code

Finally, a word from head-First:

The best way to learn design patterns is to “put them in your head and find out where you can use them in your design and in your existing applications.”

Public number: front-end growth booklet