Что такое полиморфизм в Javascript?

Я прочитал некоторую возможную статью, которую я мог найти в интернете на полиморфизм. Но мне кажется, я не совсем понял его значение. В большинстве статей не говорится, почему это важно и как я могу достичь полиморфного поведения в ООП (конечно, в JavaScript).

Я не могу предоставить пример кода, потому что у меня нет идеи, как его реализовать, поэтому мои вопросы ниже:

  1. что это?
  2. зачем нам это нужно ?
  3. как это работает?
  4. как я могу достичь этого полиморфного поведения в javascript?

У меня есть этот пример. Но легко понять, каким будет результат этого кодекса. Это не дает ясного представления о самом полиморфизме.

function Person(age, weight) {
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo.";
    }
}
function Employee(age, weight, salary) {
    this.salary = salary;
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo " +
        "and earns " + this.salary + " dollar.";
    }
}

Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
  // The argument, 'obj', can be of any kind
  // which method, getInfo(), to be executed depend on the object
  // that 'obj' refer to.

function showInfo(obj) {
    document.write(obj.getInfo() + "<br>");
}

var person = new Person(50,90);
var employee = new Employee(43,80,50000);
showInfo(person);
showInfo(employee);

6 ответов


полиморфизм является одним из принципов объектно-ориентированного программирования (ООП). Это практика проектирования объектов для совместного использования поведения и возможности переопределения общего поведения с конкретными. Полиморфизм использует преимущество наследования, чтобы это произошло.

в ООП все считается смоделированным как объект. Эта абстракция может быть взята вплоть до гаек и болтов для автомобиля или просто типа автомобиля с годом, маркой и модель.

чтобы иметь полиморфный сценарий автомобиля, был бы базовый тип автомобиля, а затем были бы подклассы, которые наследовали бы от автомобиля и обеспечивали свое собственное поведение поверх основных моделей поведения автомобиля. Например, подкласс может быть TowTruck, который все равно будет иметь марку и модель года, но может также иметь некоторые дополнительные поведения и свойства, которые могут быть такими же базовыми, как флаг для IsTowing, чтобы быть такими же сложными, как специфика лифта.

получаете возвращаясь к примеру людей и сотрудников, все сотрудники-это люди, но не все люди-это сотрудники. То есть люди будут супер-классом, а работники-суб-классом. Люди могут иметь возраст и вес, но у них нет зарплаты. Сотрудники-это люди, поэтому они будут иметь возраст и вес, но также и потому, что они сотрудники, они будут иметь зарплату.

поэтому, чтобы облегчить это, мы сначала напишем супер класс (Человек)

function Person(age,weight){
 this.age = age;
 this.weight = weight;
}

и мы дадим человеку возможность поделиться своей информацией

Person.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo.";
};

Далее мы хотим иметь подкласс Person, Employee

function Employee(age,weight,salary){
 this.age = age;
 this.weight = weight;
 this.salary = salary;
}
Employee.prototype = new Person();

и мы переопределим поведение getInfo, определив тот, который больше подходит для сотрудника

Employee.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo " +
    "and earns " + this.salary + " dollar.";  
};

они могут быть использованы аналогично вашему исходному использованию кода

var person = new Person(50,90);
var employee = new Employee(43,80,50000);

console.log(person.getInfo());
console.log(employee.getInfo());

тем не менее, здесь не так много получено с помощью наследования, так как конструктор сотрудника похож на человека, и единственная функция в прототипе переопределяется. Сила полиморфного дизайна в том, чтобы делиться поведением.


Как объясняется в этом другом ответе полиморфизм имеет различные толкования.

лучшее объяснение по этому вопросу, которое я когда-либо читал, - это статья От Luca Cardelli известный теоретик типа. Статья называется о понимании типов, абстракции данных и полиморфизма.

что это?

Cardelli определяет несколько типов полиморфизма в этом статья:

  • универсальный
    • параметрический
    • включение
  • специальные
    • oveloading
    • принуждение

возможно, в JavaScript немного сложнее увидеть эффекты полиморфизма, потому что более классические типы полиморфизма более очевидны в статически типизированных системах, тогда как JavaScript имеет динамический тип система.

Так, например, во время компиляции в JavaScript нет перегрузки метода или функции или автоматического принуждения типа. В динамичном языке мы принимаем большую часть этих вещей как должное. Не нужно что-то вроде параметрического полиморфизма в JavaScript из-за динамической природы языка.

тем не менее, JavaScript имеет форму наследования типа, которая эмулирует те же идеи полиморфизма подтипа (классифицированного как полиморфизм включения Карделли выше) в аналогично тому, что мы обычно делаем в других объектно-ориентированных языках программирования, как Java или C#, как уже говорилось в другой ответ.

другая форма полиморфизма, очень типичная для динамических языков, называется утиной типизацией.

ошибочно полагать, что полиморфизм связан только с объектно-ориентированным программированием. Другие модели программирования (функциональные, процедурные, логические и др.) предлагают различные формы полиморфизма в системах их типов, вероятно, немного незнакомым для тех, кто только привык к ООП.

Зачем Нам Это Нужно?

полиморфизм способствует многим хорошим атрибутам в программном обеспечении, среди прочего, он способствует модульности и повторному использованию и делает систему типов более гибкой и податливой. Без него было бы действительно трудно рассуждать о типах. Полиморфизм гарантирует, что один тип может быть заменен другими совместимыми при условии, что они удовлетворяют публичному интерфейсу, поэтому это также способствует скрытие и модульность информации.

как это работает?

Это не просто ответить, разные языки имеют разные способы его реализации. В случае JavaScript, как упоминалось выше, вы увидите, что он материализуется в виде иерархий типов, используя прототипного наследования и вы также можете использовать его с помощью duck typing.

тема немного широка, и вы открыли два много вопросов в одном сообщении. Возможно, будет лучше, если вы начните с чтения статьи Карделли, а затем попытайтесь понять полиморфизм независимо от любого языка или парадигмы программирования, тогда вы начнете создавать ассоциации между теоретическими концепциями и тем, что любой конкретный язык, такой как JavaScript, может предложить для реализации этих идей.


что это?

Poly= много, морфизм=форма или изменение поведения.

зачем оно нужно ?

в программировании он используется, когда мы хотим, чтобы интерфейс функции (скажем, функции X) был достаточно гибким, чтобы принимать различные типы или количество параметров. Кроме того, на основе изменения типов параметров или чисел мы можем захотеть, чтобы функция X вела себя по-разному (морфизм).

Как это работает?

мы пишем несколько реализаций функции X, где каждая реализация принимает различные типы параметров или числом параметров. На основе типа или количества параметров компилятор (во время выполнения) решает, какая реализация X должна выполняться при вызове X из некоторого кода.

Как я могу достичь этого полиморфного поведения в javascript?

JS не является типизированным языком, поэтому он действительно не предназначен для использования ООП такие понятия как полиморфизм. Однако новая версия JS теперь включает классы, и есть вероятность, что полимосфизм может начать иметь смысл и в JS. Другие ответы дают некоторые интересные обходные пути.


какова цель полиморфизма?

полиморфизм делает систему статического типа более гибкой без потери (значительной) безопасности статического типа путем ослабления условий эквивалентности типов. Доказательство остается, что программа будет работать только в том случае, если она не содержит ошибок типа.

полиморфная функция или тип данных является более общей, чем мономорфная, поскольку ее можно использовать в более широком диапазоне сценариев. В этом смысле полиморфизм представляет идею обобщения в строго типизированных языках.

как это относится к Javascript?

Javascript имеет слабую, динамическую систему типов. Такая система типов эквивалентна строгой системе типов, содержащей только один тип. Мы можем думать о таком типе как огромный тип объединения (псевдо синтаксис):

type T =
 | Undefined
 | Null
 | Number
 | String
 | Boolean
 | Symbol
 | Object
 | Array
 | Map
 | ...

каждое значение будет связана с одной из этих альтернатив типа во время выполнения. И поскольку Javascript слабо типизирован, каждое значение может изменить свой тип любым количество раз.

если мы возьмем теоретическую перспективу типа и рассмотрим, что существует только один тип, мы можем с уверенностью сказать, что система типов Javascript не имеет понятия полиморфизма. Вместо этого мы имеем типирование утки и неявное принуждение типа.

но это не должно мешать нам думать о типах в наших программах. Из-за отсутствия типов в Javascript нам нужно вывести их во время процесса кодирования. Наш разум должен стоять за пропавших без вести. как только мы смотрим на программу, мы должны распознавать не только алгоритмы, но и базовые (возможно, полиморфные) типы. Эти типы помогут нам создавать более надежные и надежные программы.

чтобы сделать это правильно, я собираюсь дать вам обзор наиболее распространенных проявлений полиморфизма.

параметрический полиморфизм (он же дженерики)

параметрический полиморфизм говорит, что разные типы взаимозаменяемы потому что типы вообще не имеют значения. Функция, определяющая один или несколько параметров параметрического полиморфного типа, не должна ничего знать о соответствующих аргументах, но относиться к ним одинаково, поскольку они могут быть приняты к любому типу. Это довольно ограничительно, потому что такая функция может работать только с теми свойствами своих аргументов, которые не являются частью их данных:

// parametric polymorphic functions

const id = x => x;

id(1); // 1
id("foo"); // "foo"

const k = x => y => x;
const k_ = x => y => y;

k(1) ("foo"); // 1
k_(1) ("foo"); // "foo"

const append = x => xs => xs.concat([x]);

append(3) ([1, 2]); // [1, 2, 3]
append("c") (["a", "b"]); // ["a", "b", "c"]

специальный полиморфизм (он же перегрузка)

ad-hoc полиморфизм говорит, что разные типы эквивалентны только для определенной цели. Эквивалентны в этом смысле тип должен реализовать набор функций, специфичных для этой цели. Функция, определяющая один или несколько параметров ad-hoc полиморфного типа, должна знать, какие наборы функций связаны с каждым из ее аргументов.

ad-hoc полиморфизм делает функцию совместимой с большей областью типов. В следующем примере показано назначение "map-over" и как типы могут реализовать это ограничение. Вместо набора функций ограничение "mappable" включает только одно map функция:

// Option type
class Option {
  cata(pattern, option) {
    return pattern[option.constructor.name](option.x);
  }
  
  map(f, opt) {
    return this.cata({Some: x => new Some(f(x)), None: () => this}, opt);
  }
};

class Some extends Option {
  constructor(x) {
    super(x);
    this.x = x;
  }
};

class None extends Option {
  constructor() {
    super();
  }
};


// ad-hoc polymorphic function
const map = f => t => t.map(f, t);

// helper/data

const sqr = x => x * x;

const xs = [1, 2, 3];
const x = new Some(5);
const y = new None();

// application

console.log(
  map(sqr) (xs) // [1, 4, 9]
);

console.log(
  map(sqr) (x) // Some {x: 25}
);

console.log(
  map(sqr) (y) // None {}
);

полиморфизм подтипа

поскольку другие ответы уже охватывают полиморфизм подтипа, я пропускаю его.

структурный полиморфизм (он же strutrual подтип)

структурный полиморфизм говорит, что разные типы эквивалентны, если они содержат одну и ту же структуру таким образом, что один тип имеет все свойства другого, но могут включать дополнительные свойства. При этом структурный полиморфизм является типизацией утки во время компиляции и, безусловно, предлагает некоторую дополнительную безопасность типа. Но, утверждая, что два значения имеют один и тот же тип только потому, что они разделяют некоторые свойства, он полностью игнорирует семантический уровень значений:

const weight = {value: 90, foo: true};
const speed =  {value: 90, foo: false, bar: [1, 2, 3]};

к сожалению, speed является подтипом weight и как только мы сравниваем value свойства мы практически сравнение яблок с апельсинами.


JavaScript-это интерпретируемый язык, а не компилируемый язык.

полиморфизм времени компиляции (или статический полиморфизм) полиморфизм времени компиляции-это не что иное,как перегрузка метода в java, c++

таким образом, перегрузка метода невозможна в javascript.

но динамический (время выполнения) полиморфизм-это полиморфизм, существующий во время выполнения таким образом, переопределение метода возможно в javascript

другой пример-PHP.


Polymorphism means Ability to call the same method on different objects and each object responds in different way is called **POLYMORPHISM**.

    function Animal(sound){
    this.sound=sound;
    this.speak=function(){
    			return this.sound;
    	}
    }
//one method 
    function showInfo(obj){
    		console.log(obj.speak());
    }
//different objects
    var dog = new Animal("woof");
    var cat = new Animal("meow");
    var cow = new Animal("humbow");
//responds different ways
    showInfo(dog);
    showInfo(cat);
    showInfo(cow);