Prototip tabanlı programlama - Prototype-based programming

Prototip tabanlı programlama , davranışın yeniden kullanımının ( kalıtım olarak bilinir ), prototip görevi gören mevcut nesnelerin yeniden kullanılması süreci aracılığıyla gerçekleştirildiği bir nesne yönelimli programlama stilidir . Bu model aynı zamanda prototip , prototip yönelimli, sınıfsız veya örnek tabanlı programlama olarak da bilinir .

Prototip tabanlı programlama, daha sonra klonlanabilen ve genişletilebilen genelleştirilmiş nesneleri kullanır. Meyveyi örnek olarak kullanırsak, bir "meyve" nesnesi genel olarak meyvenin özelliklerini ve işlevselliğini temsil eder. "Meyve" nesnesinden bir "muz" nesnesi klonlanacak ve muzlara özgü genel özellikler eklenecektir. Her bir "muz" nesnesi, genel "muz" nesnesinden klonlanacaktır. Bir "meyve" sınıfının bir "muz" sınıfı tarafından genişletileceği sınıf tabanlı paradigmayla karşılaştırın .

İlk prototip yönelimli programlama dili , 1980'lerin ortalarında David Ungar ve Randall Smith tarafından nesne yönelimli dil tasarımı konularını araştırmak için geliştirilen Self idi . 1990'ların sonlarından bu yana, sınıfsız paradigma giderek daha popüler hale geldi. Bazı akım prototip odaklı dillerdir JavaScript (ve diğer ECMAScript gibi uygulamalar JScript ve Flaş 'ın ActionScript 1.0), Lua , Cecil , NewtonScript , Io , Ioke , MOO , REBOL ve AHK .

Tasarım ve Uygulama

JavaScript'teki prototip kalıtım, Douglas Crockford tarafından şu şekilde tanımlanır :

Prototip nesneler yaparsınız ve ardından … yeni örnekler oluşturursunuz. JavaScript'te nesneler değiştirilebilir, bu nedenle yeni örnekleri artırarak onlara yeni alanlar ve yöntemler verebiliriz. Bunlar daha sonra daha yeni nesneler için prototip görevi görebilir. Bir sürü benzer nesne yapmak için sınıflara ihtiyacımız yok… Nesneler nesnelerden miras alır. Bundan daha nesne yönelimli ne olabilir?

Prototip tabanlı programlamanın savunucuları, programcıyı bir dizi örnek davranışına odaklanmaya teşvik ettiğini ve ancak daha sonra bu nesneleri, daha sonra sınıflara benzer bir şekilde kullanılan arketipsel nesnelere sınıflandırma konusunda endişelendiğini savunuyorlar . Birçok prototip tabanlı sistem, çalışma zamanı sırasında prototiplerin değiştirilmesini teşvik ederken, yalnızca çok az sınıf tabanlı nesne yönelimli sistem (dinamik nesne yönelimli sistem, Common Lisp , Dylan , Objective-C , Perl , Python , Ruby gibi) , veya Smalltalk ) bir programın yürütülmesi sırasında sınıfların değiştirilmesine izin verir.

Hemen hemen tüm prototip tabanlı sistemler, yorumlanmış ve dinamik olarak yazılan dillere dayanmaktadır . Bununla birlikte , statik olarak yazılan dillere dayalı sistemler teknik olarak mümkündür. Prototip Tabanlı Programlama'da tartışılan Omega dili böyle bir sistemin bir örneğidir, ancak Omega'nın web sitesine göre Omega bile yalnızca statik değildir, bunun yerine "derleyicisi, bunun mümkün olduğu yerlerde statik bağlama kullanmayı seçebilir ve verimliliğini artırabilir. bir program."

nesne yapımı

Prototip tabanlı dillerde açık sınıflar yoktur. Nesneler, bir prototip özelliği aracılığıyla doğrudan diğer nesnelerden miras alır. Prototip özelliği denir prototypeiçinde Öz ve JavaScript veya protoiçinde Io . Yeni nesneler oluşturmanın iki yöntemi vardır: ex nihilo ("hiçlikten") nesne oluşturma veya mevcut bir nesneyi klonlama yoluyla . İlki , nesnelerin çalışma zamanında özel sözdizimi aracılığıyla tanımlanabildiği ve doğrudan bir değişkene iletildiği bir tür nesne değişmezi , bildirimler aracılığıyla desteklenir {...}. Çoğu sistem çeşitli klonlamayı desteklerken, ex nihilo nesne oluşturma o kadar belirgin değildir.

Sınıf tabanlı dillerde, bir sınıfın yapıcı işlevi aracılığıyla yeni bir örnek oluşturulur; bu, nesnenin üyeleri (özellikler ve yöntemler) için bir bellek bloğu ayıran ve bu bloğa bir başvuru döndüren özel bir işlevdir. İşleve isteğe bağlı bir yapıcı argüman seti iletilebilir ve genellikle özelliklerde tutulur. Ortaya çıkan örnek, benzer şekilde yazılmış nesnelerin oluşturulabileceği bir tür şablon görevi gören sınıfta tanımlanan tüm yöntemleri ve özellikleri devralır.

Ex nihilo nesne oluşturmayı destekleyen sistemler, mevcut bir prototipten klonlama yapmadan sıfırdan yeni nesnelerin oluşturulmasına izin verir. Bu tür sistemler, mevcut nesnelere başvurmadan yeni nesnelerin özelliklerini ve davranışlarını belirlemek için özel bir sözdizimi sağlar. Birçok prototip dilinde , çalışma zamanında oluşturulan diğer tüm nesneler için varsayılan prototip olarak ayarlanan ve nesnenin açıklamasını bir dize olarak döndürme işlevi gibi yaygın olarak ihtiyaç duyulan yöntemleri taşıyan , genellikle Object adlı bir kök nesne vardır. toString(). Ex nihilo nesne oluşturmanın yararlı bir yönü, yeni bir nesnenin yuva (özellikler ve yöntemler) adlarının , üst düzey Nesne nesnesi ile ad alanı çakışmaları olmamasını sağlamaktır . ( JavaScript dilinde, bunu boş bir prototip kullanarak yapabilirsiniz, yani .) Object.create(null)

Klonlama , mevcut bir nesnenin (prototipinin) davranışını kopyalayarak yeni bir nesnenin oluşturulduğu bir süreci ifade eder. Yeni nesne daha sonra orijinalin tüm niteliklerini taşır. Bu noktadan itibaren, yeni nesne değiştirilebilir. Bazı sistemlerde, ortaya çıkan alt nesne , prototipine ( delegasyon veya benzerlik yoluyla) açık bir bağlantı sağlar ve prototipteki değişiklikler, karşılık gelen değişikliklerin klonunda görünür olmasına neden olur. Forth benzeri programlama dili Kevo gibi diğer sistemler, prototipten bu şekilde değişikliği yaymaz ve bunun yerine klonlanmış nesnelerdeki değişikliklerin torunlar arasında otomatik olarak yayılmadığı daha birleştirici bir model izler .

// Example of true prototypal inheritance style 
// in JavaScript.

// object creation using the literal 
// object notation {}.
const foo = { name: "foo", one: 1, two: 2 };

// Another object.
const bar = { two: "two", three: 3 };

// Object.setPrototypeOf() is a method introduced in ECMAScript 2015.
// For the sake of simplicity, let us pretend 
// that the following line works regardless of the 
// engine used:
Object.setPrototypeOf(bar, foo); // foo is now the prototype of bar.

// If we try to access foo's properties from bar 
// from now on, we'll succeed. 
bar.one; // Resolves to 1.

// The child object's properties are also accessible.
bar.three; // Resolves to 3.

// Own properties shadow prototype properties
bar.two; // Resolves to "two"
bar.name; // unaffected, resolves to "foo"
foo.name; // Resolves to "foo"

Başka bir örnek için:

const foo = { one: 1, two: 2 };

// bar.[[prototype]] = foo
const bar = Object.create(foo);

bar.three = 3;

bar.one; // 1
bar.two; // 2
bar.three; // 3

heyet

Delegasyon kullanan prototip tabanlı dillerde , dil çalışma zamanı, bir eşleşme bulunana kadar bir dizi temsilci işaretçisini (nesneden prototipine) izleyerek doğru yöntemi gönderme veya doğru veri parçasını bulma yeteneğine sahiptir . Nesneler arasında bu davranış paylaşımını oluşturmak için gereken tek şey, yetkilendirme işaretçisidir. Sınıf temelli nesne yönelimli dillerdeki sınıf ve örnek arasındaki ilişkinin aksine, prototip ile onun dalları arasındaki ilişki, alt nesnenin bu bağlantının ötesinde prototiple bir hafızaya veya yapısal benzerliğe sahip olmasını gerektirmez. Bu nedenle, alt nesne, ilişkili prototipinin yapısını sınıf tabanlı sistemlerde olduğu gibi yeniden düzenlemeden zaman içinde değiştirilmeye ve değiştirilmeye devam edebilir. Sadece verilerin değil, yöntemlerin de eklenebileceğini veya değiştirilebileceğini belirtmek de önemlidir. Bu nedenle bazı prototip tabanlı diller hem verilere hem de yöntemlere "yuvalar" veya "üyeler" olarak atıfta bulunur.

birleştirme

Gelen birleştirmeli Kevo programlama dili tarafından uygulanan yaklaşıma - - prototip görünür işaretçileri veya bir nesne klonlanmış olduğu özgün prototip bağlantılar vardır. Prototip (ana) nesne, bağlanmak yerine kopyalanır ve herhangi bir yetkilendirme yoktur. Sonuç olarak, prototipte yapılan değişiklikler klonlanmış nesnelere yansıtılmayacaktır.

Bu düzenleme altındaki temel kavramsal farklılık, bir prototip nesnede yapılan değişikliklerin klonlara otomatik olarak yayılmamasıdır. Bu bir avantaj veya dezavantaj olarak görülebilir. (Ancak, Kevo , delegasyon modelinde tipik olduğu gibi, taksonomik köken yoluyla değil , benzerliklerine dayalı olarak - aile benzerlikleri veya klon ailesi mekanizması olarak adlandırılan - nesne kümeleri arasında değişiklikleri yayınlamak için ek ilkeller sağlar .) delegasyona dayalı prototiplemenin, bir alt nesnede yapılan değişikliklerin üst öğenin sonraki çalışmasını etkileyebileceği için ek bir dezavantajı vardır. Ancak, bu sorun temsil tabanlı modele özgü değildir ve JavaScript gibi bir alt nesnede yapılan değişikliklerin her zaman alt nesnenin kendisinde kaydedilmesini ve hiçbir zaman ebeveynlerde (yani çocuğun value, ebeveynin değerini değiştirmek yerine ebeveynin değerini gölgeler).

Basit uygulamalarda, sıralı prototipleme, temsilciye dayalı prototiplemeye göre daha hızlı üye aramasına sahip olacaktır (çünkü üst nesneler zincirini takip etmeye gerek yoktur), ancak tersine daha fazla bellek kullanacaktır (çünkü tek bir yuva yerine tüm yuvalar kopyalanır). ana nesneyi gösteren yuva). Bununla birlikte, hız ve bellek arasında değiş tokuş yapılması gerekmesine rağmen, daha karmaşık uygulamalar bu sorunu önleyebilir. Örneğin, ardışık prototiplemeli sistemler, sahne arkası veri paylaşımına izin vermek için yazma üzerine kopyalama uygulamasını kullanabilir ve böyle bir yaklaşımı gerçekten Kevo takip eder. Bunun tersine, yetkilendirme tabanlı prototip oluşturmaya sahip sistemler, veri aramayı hızlandırmak için önbelleğe almayı kullanabilir .

eleştiri

Prototip tabanlı sistemleri eleştiren sınıf tabanlı nesne modellerinin savunucuları, genellikle programlama dilleri için statik tür sistemlerin savunucularının dinamik tür sistemlerine ilişkin endişelerine benzer endişelere sahiptir (bkz. veri türü ). Genellikle, bu tür endişeler şunları içerir: doğruluk , güvenlik , öngörülebilirlik , verimlilik ve programcıya aşina olmama.

İlk üç noktada, sınıflar genellikle türlere benzer olarak görülür (çoğu statik olarak yazılan nesne yönelimli dilde bu role hizmet ederler) ve örneklerine ve örneklerinin kullanıcılarına, davranacakları konusunda sözleşmeye dayalı garantiler sağlamaları önerilir. belirli bir şekilde.

Verimlilik ile ilgili olarak, sınıfları bildirmek, verimli yöntem ve örnek değişken araması geliştirmeye izin veren birçok derleyici optimizasyonunu basitleştirir . İçin Kendinden dil, çok geliştirme süresi, gelişmekte derleme ve sınıf temelli sistemlerde karşı prototip tabanlı sistemlerin performansını artırmak için teknikler yorumlama harcanmıştır.

Prototip tabanlı dillere karşı yapılan yaygın bir eleştiri , JavaScript'in popülaritesine ve pazara nüfuz etmesine rağmen, yazılım geliştiriciler topluluğunun bunlara aşina olmamasıdır . Prototip tabanlı sistemlerin bu bilgi seviyesi, JavaScript çerçevelerinin çoğalması ve Web olgunlaştıkça JavaScript'in karmaşık kullanımı ile artıyor gibi görünüyor . ECMAScript 6 , JavaScript'in mevcut prototip tabanlı kalıtımı üzerinde sözdizimsel şeker olarak sınıfları tanıttı ve nesneler oluşturmak ve kalıtımla uğraşmak için alternatif bir yol sağladı.

Prototip tabanlı programlamayı destekleyen diller

Ayrıca bakınız

Referanslar

daha fazla okuma