Я прочитал возможную статью о полиморфизме, которую смог найти в Интернете . Но я думаю, что не мог полностью понять значение этого и его важность. В большинстве статей не говорится, почему это важно и как добиться полиморфного поведения в ООП (конечно, в JavaScript).
Я не могу привести пример кода, потому что понятия не имею, как его реализовать, поэтому мои вопросы ниже:
- Что это такое?
- Зачем это нужно?
- Как это работает?
- Как я могу добиться такого полиморфного поведения в 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);
Ответы:
Полиморфизм - один из принципов объектно-ориентированного программирования (ООП). Это практика проектирования объектов, которые разделяют поведение и имеют возможность заменять общее поведение конкретным. Полиморфизм использует наследование, чтобы это произошло.
В ООП все моделируется как объект. Эта абстракция может быть выражена вплоть до гаек и болтов для автомобиля или просто типа автомобиля с годом, маркой и моделью.
Чтобы иметь сценарий полиморфного автомобиля, был бы базовый тип автомобиля, а затем были бы подклассы, которые унаследовали бы от автомобиля и предоставили бы свое собственное поведение поверх базового поведения автомобиля. Например, подклассом может быть 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.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 очень похож на конструктор пользователя, и единственная функция в прототипе переопределяется. Сила полиморфного дизайна заключается в том, чтобы делиться поведением.
источник
getInfo
которое будет для Employee, так как оно выше в цепочке, чем Person. Это то, что я имел в виду, когда сказал «переопределить».return Person.prototype.getInfo.call(this) + + "and earns " + this.salary + " dollar.";
вместо повторного использования кода копирования и вставки.Как объясняется в этом другом ответе , полиморфизм имеет разные интерпретации.
Лучшее объяснение по этому поводу, которое я когда-либо читал, - это статья Луки Карделли , известного теоретика шрифта. Статья называется « Понимание типов, абстракции данных и полиморфизма» .
Что это такое?
Карделли определяет несколько типов полиморфизма в этой статье:
Возможно, в JavaScript немного сложнее увидеть эффекты полиморфизма, потому что более классические типы полиморфизма более очевидны в системах статических типов, тогда как в JavaScript есть система динамических типов.
Так, например, в JavaScript нет перегрузки методов или функций или автоматического приведения типов во время компиляции. На динамическом языке мы принимаем большинство из этих вещей как должное. Нам также не нужно что-то вроде параметрического полиморфизма в JavaScript из-за динамической природы языка.
Тем не менее, в JavaScript есть форма наследования типов, которая имитирует те же идеи полиморфизма подтипов (классифицированных как полиморфизм включения Карделли выше) аналогично тому, что мы обычно делаем в других объектно-ориентированных языках программирования, таких как Java или C # (как описано в другой ответ, которым я поделился выше).
Другая форма полиморфизма, очень типичная для динамических языков, называется утиной типизацией .
Ошибочно полагать, что полиморфизм связан только с объектно-ориентированным программированием. Другие модели программирования (функциональные, процедурные, логические и т. Д.) Предлагают различные формы полиморфизма в своих системах типов, возможно, несколько незнакомые тем, которые используются только в ООП.
Зачем это нужно?
Полиморфизм способствует развитию множества хороших атрибутов в программном обеспечении, среди прочего он способствует модульности и возможности многократного использования, а также делает систему типов более гибкой и гибкой. Без него было бы действительно сложно рассуждать о типах. Полиморфизм гарантирует, что один тип может быть заменен другими совместимыми, при условии, что они удовлетворяют общедоступному интерфейсу, поэтому это также способствует сокрытию информации и модульности.
Как это работает?
На это непросто ответить, разные языки по-разному это реализовать. В случае с JavaScript, как упоминалось выше, вы увидите, что он материализуется в виде иерархий типов с использованием прототипного наследования, а также вы можете использовать его, используя утиную типизацию.
Тема немного широка, и вы открыли два множества вопроса в одном посте. Возможно, лучше всего начать с чтения статьи Карделли, а затем попытаться понять полиморфизм независимо от какого-либо языка или парадигмы программирования, после чего вы начнете создавать ассоциации между теоретическими концепциями и тем, что может предложить какой-либо конкретный язык, такой как JavaScript, для реализации этих идей.
источник
В чем цель полиморфизма?
Полиморфизм делает систему статических типов более гибкой без потери (значительной) безопасности статических типов за счет ослабления условий эквивалентности типов. Остается доказательство того, что программа будет работать только в том случае, если она не содержит ошибок типа.
Полиморфная функция или тип данных является более общим, чем мономорфный, потому что он может использоваться в более широком диапазоне сценариев. В этом смысле полиморфизм представляет собой идею обобщения в строго типизированных языках.
Как это применимо к 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"]
Специальный полиморфизм (он же перегрузка)
Специальный полиморфизм говорит, что разные типы эквивалентны только для определенной цели. Чтобы быть эквивалентным в этом смысле, тип должен реализовывать набор функций, специфичных для этой цели. Функция, которая определяет один или несколько параметров специального полиморфного типа, должна знать, какие наборы функций связаны с каждым из ее аргументов.
Специальный полиморфизм делает функцию совместимой с более крупной областью типов. Следующий пример иллюстрирует цель «сопоставления» и то, как типы могут реализовать это ограничение. Вместо набора функций "отображаемое" ограничение включает только одну
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
свойства, мы фактически сравниваем яблоки с апельсинами.источник
len
. Или, возможно,conj
из-за закрытия.Поли = много, морфизм = изменение формы или поведения.
В программировании он используется, когда мы хотим, чтобы интерфейс функции (скажем, функции X) был достаточно гибким, чтобы принимать различные типы или количество параметров. Кроме того, в зависимости от типа или числа параметров мы можем захотеть, чтобы функция X вела себя по-другому (морфизм).
Мы пишем несколько реализаций функции X, где каждая реализация принимает разные типы параметров или количество параметров. В зависимости от типа или количества параметра компилятор (во время выполнения) решает, какая реализация X должна выполняться, когда X вызывается из некоторого кода.
JS не является типизированным языком, поэтому на самом деле он не предназначен для использования таких концепций ООП, как полиморфизм. Однако более новая версия JS теперь включает классы, и есть вероятность, что полимосфизм может начать иметь смысл и в JS. Другие ответы предоставляют некоторые интересные обходные пути.
источник
Полиморфизм означает, что способность вызывать один и тот же метод для разных объектов, и каждый объект реагирует по-разному, называется ПОЛИМОРФИЗМ .
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);
источник
JavaScript - это интерпретируемый язык, а не компилируемый язык.
Полиморфизм времени компиляции (или статический полиморфизм) Полиморфизм времени компиляции - это не что иное, как перегрузка метода в java, c ++
Таким образом, в javascript перегрузка метода невозможна.
Но динамический (во время выполнения) полиморфизм - это полиморфизм, существующий во время выполнения, поэтому в javascript возможно переопределение метода.
другой пример - PHP.
источник