preface

You wish the world, I wish you no bugs. Hello everyone! I’m Lin Dull!

First of all, SORRY to make you wait so long, we have been looking forward to the “polymorphic” chapter until now to 😊, in fact, I am quite busy recently, let you feel a screenshot of a mobile phone.


Forget it. You’re not gonna believe me.

Because we don’t hear much about feeling polymorphism in normal development, there is a misconception that polymorphism is not important. But in fact, it plays an important role in all kinds of design patterns, most of which are inseparable from the thought of polymorphism.

This article will not go too far into design patterns, but will give you an idea of what polymorphism is and how you can implement some of it. Hopefully it will be helpful.

JS object-oriented series introduction

This series aims to give us a thorough understanding of JavaScript’s three object-oriented features: encapsulation, inheritance, and polymorphism.

Series general catalogue:

  • 🔥 [why not three even] more simple than inherit the family inheritance JS title – package (knife small test)
  • 💦【 why not three even 】 finish this 48 questions thoroughly understand JS inheritance (1.7W words with hot finishing – back to nature)
  • 🍃 [why not three even] JS object-oriented last bullet – polymorphisms (yuhua Shengxian) “this article”

This chapter explains the final feature of JS object orientation – polymorphism.

By reading this chapter you can learn:

  • A piece of code that looks “polymorphic”
  • Object polymorphism
  • The example of making a small movie
  • Strongly typed languages and polymorphism
  • Inheritance is used in TypeScript to get polymorphic effects
  • JS inherent polymorphism
  • Practical applications of polymorphism

1. A piece of code that looks “polymorphic”

One that we hear a lot is:

👣

The practical meaning of polymorphism is that the same operation on different objects can produce different interpretations and different execution results.

Let’s use an example 🌰.

Suppose I have two pets now, one is a small cat 🐱, one is a puppy 🐶. And now I’m going to give them a signal and tell them to bark.

Kittens need to say “meow, meow, meow!” while puppies need to say “woof, woof!” .

Let them call is the same operation, different calls are different execution results.

How would you design it if you wanted to convert it to code?

Let’s get this straight. We need:

  • A way to make a soundmakeSound
  • A cat classCat
  • A dog classDog
  • When callingmakeSoundAnd if the incoming is a cat, print it out"Meow, meow, meow."
  • When callingmakeSoundAnd if it’s a dog, print it out"Woof woof!

So we can easily get the following code:

function makeSound (animal{

  if (animal instanceof Cat) {

    console.log('Meow, meow, meow.')

  } else if (animal instanceof Dog) {

    console.log('Woof woof! ')

  }

}

class Cat {}

class Dog {}

makeSound(new Cat()) // 'meow meow meow ~'

makeSound(new Dog()) // 'Woof woof! '

Copy the code

👆 makeSound with different types of objects, and makeSound with different types of objects. How about 🐷? I want it to say “啂 Nini “. Does that mean I have to modify the makeSound method?

function makeSound (animal{

  if (animal instanceof Cat) {

    console.log('Meow, meow, meow.')

  } else if (animal instanceof Dog) {

    console.log('Woof woof! ')

  } else if (animal instanceof Pig) {

   console.log('啂 Nini ')

  }

}

class Cat {}

class Dog {}

class Pig {}

makeSound(new Cat()) // 'meow meow meow ~'

makeSound(new Dog()) // 'Woof woof! '

makeSound(new Pig()) // '啂 nini '

Copy the code

Every time we need to add another animal, we need to make a public method that makeSound and keeps adding conditional branches, which is obviously not what I want. Because we know that it is always dangerous to change code, especially if you change methods that are common in nature, the chances of a program going wrong increase. And as we add more animals, we’ll add more code to our makeSound function. (I can’t stand it as a programmer with professional ethics.)


2. Object polymorphism

In fact, the most fundamental function of polymorphism is to eliminate conditional branch statements by transforming procedural conditional statements into object polymorphism.

The idea behind it is, colloquially, to separate “what” from “who does it and how.” You could also think of it as separating things that don’t change from things that can change.

In this example 🌰, now that we have made it clear that all animals make noises (it is the “invariable thing “), and that how an animal makes noises is different (it is the” possible thing to change “), we can distribute the “how to make noises” actions across classes (encapsulating each class). You can then call the action within the makeSound function that makes the call.

Let’s change the title of 👆 above with the idea of polymorphism:

function makeSound (animal{

  if (animal.sound instanceof Function) { // Determine if there is animal.sound and the property is a function

    animal.sound()

  }

}

class Cat {

  sound () {

    console.log('Meow, meow, meow.')

  }

}

class Dog {

  sound () {

    console.log('Woof woof! ')

  }

}

class Pig {

  sound () {

    console.log('啂 Nini ')

  }

}

makeSound(new Cat()) // 'meow meow meow ~'

makeSound(new Dog()) // 'Woof woof! '

makeSound(new Pig()) // '啂 nini '

Copy the code

Here’s what we see: MakeSound creates a different form for each class, and if you want to add another makeSound (tiger 🐯, lion 🦁️, bear 🐻), you don’t need to change the public makeSound (sound) method. It also removes the if.. in makeSound. The else.

In this example 🌰 we isolate the sound(animal.sound()) from the sound(){console.log(‘ meow meow meow ~ ‘)}.

How else can you understand it?

Well… The cat is a kind of animal that is born with it, is I want to call it to emit a meow has been determined before, when I need it to meow it knows that they should use the “meow meow meow ~” sound.

As opposed to the beginning, where you’re a cat, but you don’t know how to meow, and when I tell you to meow and I tell you that you should meow, meow, meow, meow.

Yay, yay, yay, yay, yay, yay. Is to learn technology, you give 👴 the whole tongue twister? ! Huh? !

Well, if you don’t understand all the words above, I have to use another example to illustrate the problem.

3. Examples of making small movies

(Young people don’t have a lot of dirty things in their heads. Small movies here mean small movies with less money and fewer people.)

Now Lin Dull is the director, using the polymorphism of the object to shoot the movie. When I call action, the actor starts his performance, the photographer starts shooting, the lighting division makes good lights, and the staff of all posts know what their work is to do before they start shooting.

If I don’t use object polymorphism and I use a process-oriented approach, when I call out action, I have to go to everyone and tell them what they have to do, and they do what I tell them to do.

In association with the above example, is that true?


4. Strongly typed languages and polymorphism

Above 👆 we have been using JavaScript to illustrate the case, which should make the implementation of polymorphism seem like a very easy thing to do.

The idea comes from the common statement that JS is a weakly typed (dynamically typed) language.

When we define a variable, we don’t specify the type of the variable, but we specify it later when we assign it.

It’s like I want my pets to call this case. When I makeSound, I pass in an animal, and I don’t specify what animal it is, I don’t specify whether it’s a cat or a dog, because in JS you don’t have to do that, it’s not that restrictive.

But imagine switching to another strongly typed (static) language, one you’ve heard of, such as Java.

When I define a makeSound method, it requires me to specify the animal type, so let’s say I make cat:

public class AnimalSound {

    public void makeSound (Cat animal) // The animal type is a Cat

        animal.sound()

    }

}

Copy the code

Now when we call makeSound and pass in a Cat(new Cat()), it works.

But what if you call a makeSound method with a dog? The program doesn’t allow us to do that, because it says the animal must be a cat.

So you can see that the type checking of strongly typed languages, while providing security, also makes us feel like we’re not going to be able to do anything when we’re designing a program.

So how can you solve this problem in a strongly typed language like Java 🤔️?

Well, it’s mostly through upward transition, so just to give you a conceptual thing:

Statically typed object-oriented languages are usually designed to be upcast: when assigning a value to a class variable, the type of the variable can use either the class itself or a superclass of the class.

For example, when we describe a pet meow, we usually say: A cat meow or a dog meow. But if we ignore the specific type, we can say: an animal is calling.

Similarly, here we can design a type: Animal. When the Cat and Dog types are hidden behind the supertype Animal, Cat and Dog can be used interchangeably.

This is the way to get objects to behave polymorphically, which is the goal of many design patterns.

As boring as this may sound, let’s look at the TypeScript example below.

5. Use inheritance to get polymorphic effects in TypeScript

If you think you don’t understand Java and don’t want to read it, I’ll use TypeScript as an example. It is known to allow us to write “statically typed JS”. I use it to make an upward transition from static typing.

(Well, TypeScript is used differently than some truly statically typed languages, but I’m using it for your convenience.)

Now I assign a makeSound method of type Animal to the makeSound method as mentioned above at 👆, which specifies that the incoming object must be able to speak:

(It’s ok not to know TypeScript, but that’s a good reason not to read the following, I’ll try to be more specific 😊)

interface Animal {

  sound(): void

}

function makeSound (animal: Animal{

  animal.sound()

}

Copy the code

MakeSound (makeSound) : makeSound (makeSound)

  • You need to pass in aanimalThe object must beAnimalThe type of
  • whileAnimalType (withinterfaceThe definition is calledinterface) is a mustsoundmethods
  • So we can get: incominganimalObject must havesoundmethods

(sound(): void defines a method called sound and returns a null value.)

So now let’s design Cat and Dog:


As in this code, I’ve hidden Dog’s sound method, so the type check is already wrong when we call makeSound, which requires that the object we pass in must have a sound attribute.

(As an extension, you can also modify the configuration in tsconfig.json: “noImplicitAny”: False, your function makeSound(animal) {} and animal doesn’t have to be a type, but that misses the point of the case.

In this case, we can use interface inheritance to design such a polymorphic function:

interface Animal {

  sound(): void

}

function makeSound (animal: Animal{

  animal.sound()

}

class Cat implements Animal // implements the Animal interface

  sound(): void {

    console.log('Meow, meow, meow.')

  }

}

class Dog implements Animal {

  sound(): void {

    console.log('Woof woof! ')

  }

}

maekSound(new Cat())

makeSound(new Dog())

Copy the code

We see a new API, implements.

It acts much like extends, except that extends is followed by a class, whereas implements inherits an interface (that is, something declared with an interface)

Cat and Dog, which inherit from the implements interface, mean that they must have sound methods.

For example, I removed sound from Dog again:


Now I’m getting an error when I define the Dog class.

6. Inherent polymorphism of JS

As we can see from the examples above at 👆, the idea of polymorphism is actually to separate the “what” from the “who”, and the main thing to achieve this is to decouple the types first.

The coupling is exactly what we saw in the Java example. Once we specify that Animal is a Cat, that animal cannot be passed to a Dog object. That is, once we specify that a method’s argument is of a type, it cannot be replaced with another type.

The TypeScript example shows that Java, a statically typed language, can be transformed upward to achieve polymorphism.

But what about JS? Its variable type is variable at run time. My animal parameter can be Cat or Dog. The program doesn’t ask me to specify its type, that is, there is no coupling between these types.

This also shows that whether something can be called depends only on whether it has a sound method, not whether it is a certain type of object.

For example, in the following case 🌰, I have designed a Phone class that is not of an animal type, but has the sound method, so it can also be called:


inJSIt does not require techniques such as upward transformation to achieve polymorphic effects.

7. Practical application of polymorphism

If you haven’t been exposed to some design patterns, you probably haven’t felt the importance of them. In fact, the realization of most design patterns is inseparable from the thought of polymorphism, such as combination pattern, strategy pattern and so on. (Lin Dai will also write a series on design patterns 😊, but not so soon)

In practical work, Lin Daobai has never used it, so he dare not jump to the conclusion that it is not used much. Here on the Internet is to search for its practical application, nine out of ten cases are and “JavaScript design patterns and development practice” in the book Baidu Map Google map case.

What’s wrong with young people these days? Can’t they have new ideas?

I don’t need Baidu and Google map, I use Gaode and Sogou map! Car-scrapping ~

Here’s the case, which is actually similar to the one I started with, and you can look at the problem and figure out how to do it yourself.

Let’s say we want to write a map application and we have two alternative map API providers to access our application. However, we are not sure which one will actually be used, and both maps’ apis provide a show method, which is responsible for displaying the entire map on the page. Please use the idea of polymorphism to design a showMap method, pass in different map vendors to render different maps.

  • Scott: GaodeMap
  • Sogou: SogouMap

The code is as follows:

class GaodeMap {

  show () {

    console.log('Amap continues to guide you')

  }

}

class SogouMap {

  show () {

    console.log('Welcome to Sogou Map')

  }

}

function showMap (map{

  if (map.show instanceof Function) {

    map.show()

  }

}

showMap(new GaodeMap())

showMap(new SogouMap())

Copy the code

Refer to the article

Knowledge is priceless, support original.

Reference article:

  • A Brief Introduction to JavaScript object-oriented and its Encapsulation, Inheritance, polymorphism
  • Three features of Js: Encapsulation, Inheritance and Polymorphism
  • JavaScript Design Patterns and Development Practices

After the language

You wish the world, I wish you no bugs. So much for this article.

The guy who likes Lin Dull also hopes to follow Lin’s public account LinDaiDai or scan the following QR code 👇👇👇.


I will update some front-end knowledge content and my original article 🎉 from time to time

Your encouragement is the main motivation for my continuous creation 😊.

Related recommendations:

The most detailed BPMN.js textbook in the whole Web

If you don’t understand Babel, I’ll send you a mask.

“[Suggested stars] To come to 45 Promise interview questions a cool end (1.1W words carefully arranged)”

“[suggestion 👍] 40 more this interview questions sour cool continue (1.2W word by hand)”

“[why not three even] more simple than inheritance of JS inheritance – packaging (small test)”

【 Why not three times 】 finish these 48 questions to thoroughly understand JS inheritance (1.7W words including hot finishing – back to nature)

Data type conversion from 206 console.log()

This article is formatted using MDNICE