it-swarm.com.ru

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

Я прочитал некоторые возможные статьи, которые я мог найти в Интернете полиморфизм. Но я думаю, что не мог полностью понять значение этого и его важность. В большинстве статей не говорится, почему это важно и как я могу достичь полиморфного поведения в OOP (конечно, в 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);
76
AL-zami

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

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

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

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

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

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

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());

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

87
Travis J

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

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

Что это?

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

  • Универсальный
    • параметрический
    • включение
  • Для этого случая
    • oveloading
    • принуждение

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

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

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

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

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

Зачем нам это нужно?

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

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

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

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

23
Edwin Dalorzo

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

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

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

Как это относится к 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"]

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

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

Специальный полиморфизм делает функцию совместимой с большей областью типов. Следующий пример иллюстрирует цель "наложения на карту" и то, как типы могут реализовать это ограничение. Вместо набора функций ограничение "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 {}
);

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

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

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

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

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

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

8
user6445533

что это?

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

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

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

Как это устроено?

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

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

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

6
hadaytullah

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

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

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

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

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

2
Apoorv

Полиморфизм означает, что способность вызывать один и тот же метод для разных объектов, и каждый объект отвечает по-своему, называется ПОЛИМОРФИЗМ.

    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);
0
SooRaj Patil