Polimorfizmin amacı nedir?
Polimorfizm, tip eşdeğerliği koşullarını gevşeterek statik tip bir sistemi (önemli) statik tip güvenliğini kaybetmeden daha esnek hale getirir. Bunun kanıtı, bir programın yalnızca herhangi bir tür hatası içermediğinde çalışacağıdır.
Bir polimorfik fonksiyon veya veri tipi, monomorfik bir fonksiyondan daha geneldir, çünkü daha geniş bir senaryo yelpazesinde kullanılabilir. Bu anlamda polimorfizm, katı şekilde yazılmış dillerdeki genelleme fikrini temsil eder.
Bu, Javascript için nasıl geçerlidir?
Javascript zayıf, dinamik bir tip sistemine sahiptir. Böyle bir tip sistemi, sadece bir tip içeren katı tip sistemle eşdeğerdir. Böyle bir türü büyük bir birleşim türü olarak düşünebiliriz (sözde sözdizimi):
type T =
| Undefined
| Null
| Number
| String
| Boolean
| Symbol
| Object
| Array
| Map
| ...
Her değer, çalışma zamanında bu tür alternatiflerden biriyle ilişkilendirilecektir. Ve Javascript zayıf bir şekilde yazıldığından, her değer türünü istediğiniz kadar değiştirebilir.
Bir tip teorik perspektifi alırsak ve sadece bir tip olduğunu düşünürsek, Javascript'in tip sisteminin bir polimorfizm kavramına sahip olmadığını kesin olarak söyleyebiliriz. Bunun yerine ördek yazma ve örtük tür zorlama var.
Ancak bu bizi programlarımızdaki türleri düşünmekten alıkoymamalıdır. Javascript'teki türlerin eksikliğinden dolayı, kodlama sürecinde bunları çıkarmamız gerekir. Zihnimiz eksik derleyicinin yerine geçmelidir, yani bir programa bakar bakmaz, sadece algoritmaları değil, aynı zamanda temeldeki (belki polimorfik) türleri de tanımalıyız. Bu türler, daha güvenilir ve daha sağlam programlar oluşturmamıza yardımcı olacaktır.
Bunu düzgün bir şekilde yapabilmek için, size polimorfizmin en yaygın tezahürlerine genel bir bakış sunacağım.
Parametrik polimorfizm (jenerik olarak da bilinir)
Parametrik polimorfizm, farklı türlerin birbirinin yerine geçebileceğini söylüyor çünkü türlerin hiç önemi yok. Parametrik polimorfik tipin bir veya daha fazla parametresini tanımlayan bir fonksiyon, karşılık gelen argümanlar hakkında hiçbir şey bilmemeli, ancak hepsini aynı şekilde ele almalıdır çünkü herhangi bir türe uyarlayabilirler. Bu oldukça kısıtlayıcıdır, çünkü böyle bir işlev yalnızca kendi verilerinin parçası olmayan argümanlarının özellikleriyle çalışabilir:
const id = x => x;
id(1);
id("foo");
const k = x => y => x;
const k_ = x => y => y;
k(1) ("foo");
k_(1) ("foo");
const append = x => xs => xs.concat([x]);
append(3) ([1, 2]);
append("c") (["a", "b"]);
Ad-hoc polimorfizm (aka aşırı yükleme)
Ad-hoc polimorfizm, farklı türlerin yalnızca belirli bir amaç için eşdeğer olduğunu söyler. Bu anlamda eşdeğer olması için, bir türün bu amaca özgü bir dizi işlev gerçekleştirmesi gerekir. Ad-hoc polimorfik tipin bir veya daha fazla parametresini tanımlayan bir fonksiyon, daha sonra argümanlarının her biriyle hangi fonksiyon setlerinin ilişkilendirildiğini bilmesi gerekir.
Ad-hoc polimorfizmi, bir işlevi daha geniş bir tür alanıyla uyumlu hale getirir. Aşağıdaki örnek, "eşleme" amacını ve türlerin bu kısıtlamayı nasıl uygulayabileceğini gösterir. Bir işlev kümesi yerine "eşlenebilir" kısıtlaması yalnızca tek bir map
işlevi içerir :
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();
}
};
const map = f => t => t.map(f, t);
const sqr = x => x * x;
const xs = [1, 2, 3];
const x = new Some(5);
const y = new None();
console.log(
map(sqr) (xs)
);
console.log(
map(sqr) (x)
);
console.log(
map(sqr) (y)
);
Alt tip polimorfizmi
Diğer cevaplar zaten alt tip polimorfizmi kapsadığı için onu atlıyorum.
Yapısal polimorfizm (diğer adıyla strutrual alt tipleme)
Yapısal polimorfizm, farklı türlerin eşdeğer olduğunu, aynı yapıyı bu şekilde içeriyorlarsa, bir türün diğerinin tüm özelliklerine sahip olduğunu ancak ek özellikler içerebileceğini söyler. Bununla birlikte, yapısal polimorfizm derleme zamanında ördek yazmadır ve kesinlikle bazı ek tip güvenliği sunar. Ancak iki değerin sırf bazı özellikleri paylaştıkları için aynı türde olduğunu iddia ederek, değerlerin anlamsal düzeyini tamamen yok sayar:
const weight = {value: 90, foo: true};
const speed = {value: 90, foo: false, bar: [1, 2, 3]};
Ne yazık ki, speed
bir alt türü olarak kabul edilir weight
ve value
özelliklerini karşılaştırır karşılaştırmaz, elmaları neredeyse portakallarla karşılaştırırız.