Prosedürel / fonksiyonel programlama, Turing argümanlarına (dilimin Turing gücü var ve başka bir şey yapabilecek her şeyi yapabilir) girmeden bile OOP'tan daha zayıf değildir, ki bu çok fazla bir şey ifade etmez. Aslında, nesne yönelimli teknikler ilk olarak yerleşik olmayan dillerde denenmiştir. Bu anlamda OO programlama yalnızca belirli bir prosedürel programlama stilidir . Ancak , programın anlaşılabilirliği ve bakımı için gerekli olan modülerlik, soyutlama ve bilgi gizleme gibi belirli disiplinlerin uygulanmasına yardımcı olur .
Bazı programlama paradigmaları, teorik hesaplama vizyonundan evrilir. Lisp gibi bir dil lambda hesabı ve dillerin meta-daireselliği fikrinden evrimleşmiştir (doğal dilde refleksiviteye benzer). Korna hükümleri Prolog ve kısıt programlama programlıydı. Algol ailesi ayrıca yerleşik yansıma olmadan lambda kalkülüsüne borçludur.
Lisp, çift genetik mirasına kadar izlenebilir olan birçok programlama dili yeniliğinin test edilmiş hali olduğu için ilginç bir örnektir.
Ancak diller genellikle yeni isimler altında gelişir. Evrimin önemli bir faktörü programlama uygulamasıdır. Kullanıcılar, okunabilirlik, sürdürülebilirlik, doğruluk olasılığı gibi programların özelliklerini geliştiren programlama uygulamalarını tanımlar. Daha sonra, programların kalitesini artırmak için bu uygulamaları destekleyecek ve bazen de uygulayacak olan dil özelliklerini veya kısıtlamalarını eklemeye çalışırlar.
Bunun anlamı, bu uygulamaların eski programlama dilinde zaten mümkün olmasıdır, ancak bunları kullanmak için anlayış ve disiplin gerekir. Bunları belirli sözdizimiyle birincil kavramlar olarak yeni dillere dahil etmek, bu uygulamaların, özellikle daha az karmaşık kullanıcılar (yani büyük çoğunluk) için kullanımını ve kolayca anlaşılmasını sağlar. Ayrıca, sofistike kullanıcılar için hayatı biraz daha kolaylaştırır.
Bir şekilde, bir programa bir alt programın / fonksiyonun / prosedürün ne olduğunu dil tasarlamaktır. Yararlı kavram belirlendikten sonra, bir ad (muhtemelen) ve bir sözdizimi verilir, böylece bu dil ile geliştirilen tüm programlarda kolayca kullanılabilir. Ve başarılı olduğunda, gelecekteki dillere de dahil edilecektir.
Örnek: nesne yönlendirmesini yeniden oluşturma
Şimdi bunu bir örnek üzerinde göstermeye çalışıyorum (ki bu kesinlikle daha da cilalanabilir, zaman verildi). Örneğin amacı, nesne yönelimli bir programın muhtemelen programlama ve sürdürülebilirlik pahasına prosedürel programlama tarzında yazılabileceğini göstermek değildir. OO tesisleri olmayan bazı dillerin , modülerlik, soyutlama ve bilgi gizleme de dahil olmak üzere program organizasyonu ile ilgili niteliklerinden yararlanmak için Nesne Yönelimini etkili bir şekilde taklit etmek için aslında daha yüksek dereceli işlevler ve veri yapısı kullanabileceğini göstermeye çalışacağım. .
Dediğim gibi Lisp, OO paradigması da dahil olmak üzere birçok dil gelişiminin test edildi (ilk OO dili olarak kabul edilebilecek şey Algol ailesinde Simula 67 idi). Lisp çok basittir ve temel yorumlayıcısının kodu bir sayfadan daha azdır. Ancak Lisp'de OO programlama yapabilirsiniz. Tek ihtiyacınız olan daha üst düzey işlevler.
Sunumu basitleştirmek için ezoterik Lisp sözdizimini değil, sözde kodu kullanacağım. Ve basit bir temel problemi ele alacağım: bilgi gizleme ve modülerlik . Kullanıcının uygulamaya erişmesini (çoğunu) engellerken bir nesne sınıfı tanımlama.
Vektör ekleme, vektör boyutu ve paralellik gibi yöntemler ile 2 boyutlu vektörleri temsil eden vector adında bir sınıf oluşturmak istediğimizi varsayalım.
function vectorrec () {
function createrec(x,y) { return [x,y] }
function xcoordrec(v) { return v[0] }
function ycoordrec(v) { return v[1] }
function plusrec (u,v) { return [u[0]+v[0], u[1]+v[1]] }
function sizerec(v) { return sqrt(v[0]*v[0]+v[1]*v[1]) }
function parallelrec(u,v) { return u[0]*v[1]==u[1]*v[0]] }
return [createrec, xcoordrec, ycoordrec, plusrec, sizerec, parallelrec]
}
Sonra yaratılan vektörü kullanılacak gerçek fonksiyon isimlerine atayabilirim.
[vektör, xcoord, ycoord, vplus, vsize, vparallel] = vectorclass ()
Neden bu kadar karmaşık? Çünkü fonksiyon vektörüsünde aracı yapıları tanımlayabiliyorum ki, modülerliği korumak için programın geri kalanında görünmek istemiyorum.
Kutupsal koordinatlarda başka bir koleksiyon yapabiliriz
function vectorpol () {
...
function pluspol (u,v) { ... }
function sizepol (v) { return v[0] }
...
return [createpol, xcoordpol, ycoordpol, pluspol, sizepol, parallelpol]
}
Ama kayıtsızca her iki uygulamayı da kullanmak isteyebilirim. Bunu yapmanın bir yolu, tüm değerlere bir yazım bileşeni eklemektir ve aynı ortamda yukarıdaki tüm işlevleri tanımlamaktır: Daha sonra, döndürülen işlevlerin her birini tanımlayabilir, böylece önce koordinat türünü test eder, ardından belirli işlevi uygular onun için.
function vector () {
...
function plusrec (u,v) { ... }
...
function pluspol (u,v) { ... }
...
function plus (u,v) { if u[2]='rec' and v[2]='rec'
then return plusrec (u,v) ... }
return [ ..., plus, ...]
}
Ne kazandım: belirli işlevler görünmez kalır (yerel tanımlayıcıların kapsamı nedeniyle) ve programın geri kalanı yalnızca vectorclass çağrısı tarafından döndürülen en soyut olanları kullanabilir.
Bir itiraz, programdaki soyut işlevlerin her birini doğrudan tanımlayabilmem ve koordinat türüne bağlı işlevlerin tanımının içinde bırakabilmemdir. Sonra da gizlenirdi. Bu doğrudur, ancak daha sonra her bir koordinat türü için kod, programa yayılmış küçük parçalar halinde kesilir, bu da daha az tekrarlanabilir ve bakımı yapılabilir.
Aslında, onlara bir isim vermek zorunda değilim ve sadece tür ve işlev adını temsil eden bir dize ile dizinlenmiş bir veri yapısında anonim fonksiyonel değerleri tutabilir. Fonksiyon vektörüne lokal olan bu yapı, programın geri kalanından görünmez olacaktır.
Kullanımı basitleştirmek için, bir işlev listesi döndürmek yerine, argüman olarak açıkça yazılan bir değer ve dize alarak tek bir işlevi döndürebilir ve işlevi uygun tür ve adla uygulayabilirim. Bu, bir OO sınıfı için bir yöntem çağırmaya çok benziyor.
Burada, nesne yönelimli bir tesisin yeniden inşasında duracağım.
Yapmaya çalıştığım şey, kalıtım ve diğer benzeri özellikler de dahil olmak üzere yeterince güçlü bir dilde kullanılabilir nesne yönelimi oluşturmanın çok zor olmadığını göstermektir. Tercümanın metacirkülaritesi yardımcı olabilir, ancak çoğunlukla ihmal edilemez olmaktan çok sözdizimsel düzeyde.
Nesne yöneliminin ilk kullanıcıları kavramları bu şekilde denedi. Ve bu genellikle programlama dillerindeki birçok iyileştirme için geçerlidir. Tabii ki, teorik analizin de bir rolü vardır ve bu kavramların anlaşılmasına veya geliştirilmesine yardımcı olmuştur.
Ancak OO özelliği olmayan dillerin bazı projelerde başarısızlığa mahkum olduğu fikri basitçe garanti edilmez. Gerekirse, bu özelliklerin uygulanmasını oldukça etkili bir şekilde taklit edebilirler. Pek çok dil, yerleşik olmasa bile nesne yönelimini oldukça etkili bir şekilde yapmak için sözdizimsel ve anlamsal güce sahiptir. Ve bu bir Turing argümanından daha fazlası.
OOP, diğer dillerin sınırlamalarını ele almaz, ancak daha iyi program yazmaya yardımcı olan programlama yöntemlerini destekler veya uygular , böylece daha az deneyimli kullanıcıların bu destek olmadan kullandığı ve geliştirdiği daha gelişmiş programcıların iyi uygulamalarını takip etmesine yardımcı olur.
Tüm bunları anlamak için iyi bir kitabın Abelson & Sussman olabileceğini düşünüyorum : bilgisayar programlarının yapısı ve yorumu .