İçeriğe atla

Dinamik iletim

Vikipedi, özgür ansiklopedi

Bilgisayar programlamadadinamik iletim,altyordam çağrılarının ilişkin altyordam başlangıç adresinedinamik olarak bağlanmasıdır.Bir diğer deyişle, dinamik iletim program metnindeki bir çağrı ile işletilen altyordamın programın çalışması sırasında birbirine bağlanması durumudur.Geri çağrıveçokbiçimliliğinrealize edilmesinde kullanılan bu bağlama yöntemi,yordamsal programlamadillerinde altyordam göstericileriyle gerçekleştirilirken, nesne yönelimli dillerdekalıtlamavegerçekleştirmeilişkilerinin kullanılmasıyla otomatikman sağlanır. Altyordamların birinci sınıf dil öğesi olarak ele alındığıfonksiyonel programlamadillerinde ise, aynı işlevsellik altyordamların argüman olarak geçirilmesi ile sağlanabilir.

Dinamik İletim ve Diğer Kavramlar

[değiştir|kaynağı değiştir]

Dinamik iletimin başlıca amacı, kullanıcının gereksinimlerine göre değişkenlik gösterebilecek kod parçalarının kullanıcı tarafından tamamlanmasını mümkün kılarak yazılım çerçevelerinin çokbiçimli kullanılabilmesini sağlamak ve böylece daha yüksek yeniden kullanım elde etmektir. Örnek olarak, görsel arayüzlü bir yazılımı kullanırken yaptıklarınızı düşünün, düğmelere basıyorsunuz, metin kutularını dolduruyorsunuz, listelerden seçimler yapıyorsunuz, vs. Ancak, düğmenin (ve diğer görsel öğelerin) davranışı temelde değişmediği halde, düğmeye basıldığında programın amacına dönük şeyler oluyor. Mesela, öğrenci kayıt formunun doldurulması sonrasında tıklanan Tamam düğmesi öğrenci kaydını yaparken, kitap alışverişi sitesindeki aynı görünüşlü düğmeyi tıklamanız kitapların evinize kadar gelmesini sağlayan bir sürecin başlamasına neden oluyor. Tıklamak eylemi aynıyken, olup biten değişiyor ve bunun görsel arayüz kitaplığını üreten firma tarafından bilinmesi olanaksız; resmin sizin kullandığınız yazılımı—öğrenci kayıt ve kitap alışveriş yazılımları—üretenler tarafından doldurulması gerekli. İşte bu, yordamsal programlama dillerinde altyordam göstericilerine uygun altyordamların adreslerini geçirerek sağlanırken, nesne yönelimli dillerde yazılım çerçevesince sağlanan üstsınıflardan kalıtlama veya arayüzleri gerçekleştirme ile sağlanabilir.

Üstsınıftan kalıtlama veya arayüz gerçekleştirme senaryosunun geçerli olduğu durumlarda, bir nesneye gönderilen ileti sonucunda hangi metodun çağrılacağını belirleyen aşağıdaki adımların akılda tutulması yararlı olacaktır.

  1. İletinin uygunluğu tutacak—gösterici veya referans da olabilir—türünün (statik tür) desteklediği iletilerle denetlenir. Derleme sırasında yapılan bu denetim, ileti ve metot imzalarının uyuşup uyuşmadığına bakar. Uyuşmanın olmaması durumunda, derleme hata mesajı vererek başarısız bir biçimde sona erecek ve bir sonraki adıma geçilmeyecektir.
  2. Tutacağın temsil ettiği nesnenin sınıfına (dinamik tür) bakarak hangi metodun çağrılacağına karar verilir. Bu karar, nesnenin sınıfında gerçekleştirilen veya üstsınıflardan kalıtlanan metotlardan biri seçilerek programın çalışması sırasında verilir.

Programlama Dilleri ve Dinamik İletim

[değiştir|kaynağı değiştir]

Kabarcık sıralamasıalgoritmasınınCprogramlama dilindekisoysalgerçekleştirimini içeren aşağıdakikabarcik_siralamafonksiyonunun imzasında iki nokta dikkat çekiyor: fonksiyon göstericisi ve eleman türü olarakvoid*ile eşanlamlı ilan edilmiş olanObject.Bunlardan ilki dizinin eleman türüne ve/veya sıralama fonksiyonunun kullanılış bağlamına göre farklı biçimlerde sıralanmasını olanaklı kılarken, ikincisi dizinin herhangi bir türden eleman tutabilmesini—yani, dizinin soysal olmasını—sağlıyor.

Kabarcik.h
#ifndef KABARCIK_H
#define KABARCIK_H

typedefvoid*Object;
typedefint(*KARSILASTIRMA_FONK)(Object,Object);

externvoidkabarcik_siralama(Objectdizi[],intboy,KARSILASTIRMA_FONKkar_fonk);
#endif

Yukarıda sağlanan imzaya uygun gerçekleştirime göz atıldığında ise, işin püf noktasının fonksiyon göstericisinin kullanıldığı içteki döngünün ilk satırında olduğu görülür. Her ne kadarkaradındaki bir fonksiyonun çağrılması ile aynı görünse de, aslında bu satırdakaradlı fonksiyon göstericisinin sahip olduğu değerin işaret ettiği bellek konumunda başlayan bir fonksiyon çağrılmaktadır;kabarcik_siralamafonksiyonunun çağrıldığı noktalardakarparametresine değişik değerlere sahip göstericilerin geçirilmesi, farklı karşılaştırma ölçütlerinin kullanılması ve dolayısıyla sıralamanın farklı türler ve/veya biçimlerde yapılması anlamına gelecektir.

Kabarcik.c
#include<stdio.h>
#include"Kabarcik.h"

#define BOOL char
#define FALSE 0
#define TRUE 1

staticvoidtakas_et(Objectdz[],intsol_indis,intsag_indis){
Objectgecici=dz[sol_indis];
dz[sol_indis]=dz[sag_indis];
dz[sag_indis]=gecici;
}/* void takas_et(Object[], int, int) sonu */

voidkabarcik_siralama(Objectdz[],intboy,KARSILASTIRMA_FONKkar){
intgecis,j;

for(gecis=1;gecis<boy;gecis++){
BOOLtakas_var=FALSE;

for(j=0;j<boy-gecis;j++)
if(kar(dz[j],dz[j+1])>0){
takas_et(dz,j,j+1);
takas_var=TRUE;
}/* if sonu */
if(!takas_var)return;
}/* for(gecis = 1; gecis < boy; gecis++) sonu */
}/* void kabarcik_siralama(Object[], int, KARSILASTIRMA_FONK) sonu */

Aşağıda sağlanan sınama programının incelenmesi olup bitenin daha iyi anlaşılmasını sağlayacaktır.kabarcik_siralamafonksiyonunun ilk kullanılışıIntegertürlü elemanları olan bir diziyi karşılaştırma amacıylaint_karsfonksiyonundan yararlanarak sıralarken, ikinci kullanılış komut satırında geçirilen karakter katarı dizisini karşılaştırmak içinkarakter_katarı_karsfonksiyonundan yararlanarak sıralıyor.[1]

Kabarcik_Sinama.c
#include<stdio.h>
#include<string.h>
#include"Kabarcik.h"

typedefint*Integer;

voidksa_bas(char*ksa[],intboy){...}

voidintleri_bas(Integerdz[],intboy){...}

intkarakter_katar_kars(Objectsol,Objectsag){
return(strcmp((char*)sol,(char*)sag));
}/* int karakter_katar_kars(Object, Object) sonu */

intint_kars(Objectsol,Objectsag){
Integerig1=(Integer)sol;
Integerig2=(Integer)sag;

if(*ig1>*ig2)return1;
elseif(*ig1<*ig2)return-1;
elsereturn0;
}/* int int_kars(Object, Object) sonu */

intmain(intargs,char*ksa[]){
intdizi[]={1,3,102,6,34,12,35},i;
Integerint_dz[7];
for(i=0;i<7;i++)int_dz[i]=&dizi[i];

printf("\nTAMSAYI DIZISI SINANIYOR\n\nSiralama oncesi\n");
intleri_bas(int_dz,7);
kabarcik_siralama((Object*)int_dz,7,&int_kars);
printf("\nSiralama sonrasi\n");intleri_bas(int_dz,7);

printf("\nKARAKTER KATARI DIZISI SINANIYOR\n\nSiralama oncesi\n");
ksa_bas(&ksa[1],args-1);
kabarcik_siralama((Object*)&ksa[1],args-1,karakter_katari_kars);
printf("Siralama sonrasi\n");ksa_bas(&ksa[1],args-1);

return(0);
}/* int main(int, char **) sonu */

C'nin nesne yönelimli ardılı olanC++'da dinamik iletim, fonksiyon göstericilerine ek olarak, üstsınıftavirtualilan edilen bir fonksiyonun altsınıflarda ihtiyaca uygun bir biçimde gerçekleştirilmesi veya ezilmesi ile sağlanır. Varsayılan iletim biçiminin statik olması nedeniyle, söz konusu fonksiyonunvirtualilan edilmemesi dinamik iletimi ve dolayısıyla çokbiçimliliği engelleyecektir. Unutulmaması gereken bir diğer nokta, çokbiçimliliğin üstsınıf türünden bir gösterici veya referans—bir başka deyişle, derleyici tarafından özel bir biçimde ele alınan sabit gösterici—ile mümkün olduğudur. Bu, üstsınıf ve altsınıf nesnelerinin muhtemelen değişik büyüklüklerde olması, büyüklüğü çalışma anında belirlenebilen bellek bölgelerinin yığın bellekten ayrılması gerekliliği ve yığın belleğin ancak göstericiler ile işlenebilmesi nedeniyle zorunludur.

Memur.hxx
#ifndef MEMUR_HXX
#define MEMUR_HXX
classMemur{
...
public:
virtualdoubleaylik_gelir()=0;
...
};// Memur sinifinin sonu
#endif

İkinci aşamada yapılması gereken, dinamik iletimli çağrılacağı içinvirtualilan edilmiş olan fonksiyonların altsınıflarda tanımlanmakta olan türlerin özelliklerini göz önünde bulundurarak gerçekleştirmektir.

GenelMudur.hxx
#ifndef GENELMUDUR_HXX
#define GENELMUDUR_HXX
#include"Memur.hxx"

classGenelMudur:publicMemur{...};
#endif
GenelMudur.c
#include"GenelMudur.hxx"
...
doubleGenelMudur::aylik_gelir(){
// Geliri derece, kademe ve alınabilecek rüşveti hesaba katarak hesapla.
}// double GenelMudur::aylik_gelir() sonu
...
DuzMemur.hxx
#ifndef DUZMEMUR_HXX
#define DUZMEMUR_HXX
#include"Memur.hxx"

classDuzMemur:publicMemur{...};
#endif
DuzMemur.c
#include"DuzMemur.hxx"
...
doubleDuzMemur::aylik_gelir(){
// Geliri derece ve kademeden yararlanarak hesapla.
}// double DuzMemur::aylik_gelir() sonu
...

Dinamik iletimli fonksiyonun çokbiçimli kullanımına bir örnek aşağıdaki kod parçasından görülebilir. Dikkat edilecek olursa,memurlaradındaki kabın eleman türü üstsınıfın referans türüne sahip tanımlanmış. Dolayısıyla, söz konusu kapMemurveyaMemurgibi olan—yani,Memur'dan kalıtlayan—herhangi bir türden nesneyi gösteren referanslar tutacaktır.[2]

Bordro.cpp
#include<vector>
usingnamespacestd;
#include"Memur.hxx"
#include"GenelMudur.hxx"
#include"DuzMemur.hxx"

intmain(void){
vector<Memur&>memurlar;
...
doubletoplam_odeme=0;
vector<Memur&>::const_iteratorbas=memurlar.begin(),son=memurlar.end();
while(bas!=son){
toplam_odeme+=(*bas).aylik_gelir();
bas++;
}// while (bas!= son) sonu
...
}// int main(void) sonu

Java'da,finalilan edilerek aksi söylenmedikçe, tüm metotlar dinamik iletimle çağrılır. Dolayısıyla, programcının fazladan bir şey yapmasına gerek yoktur.

Kalıtlama Yoluyla Çokbiçimlilik ve Dinamik İletim

[değiştir|kaynağı değiştir]
Memur.java
publicabstractclassMemur{
...
publicdoublegelir();
...
}// Memur sınıfının sonu
GenelMüdür.java
publicclassGenelMüdürextendsMemur{
...
publicdoublegelir(){
// Geliri derece, kademe ve alınabilecek rüşveti hesaba katarak hesapla.
}
...
}// GenelMüdür sınıfının sonu
DüzMemur.java
publicclassDüzMemurextendsMemur{
...
publicdoublegelir(){
// Geliri derece ve kademeden yararlanarak hesapla.
}
...
}// DüzMemur sınıfının sonu

Kalıtlama yoluyla çokbiçimliliğin örneklendiği aşağıdaki kod parçasından da görülebileceği gibi, gönderilen ileti sonucunda çağrılan metot, tutacağın arkasındaki nesnenin türüne göre belirlenmektedir. Buna göre,fordöngüsünün içindekigeliriletisi, kimi zamanGenelMüdürkimi zamansaDüzMemursınıfındaki aynı imzalı metodun çağrılmasına neden olacaktır.

Bordro.java
importjava.util.Vector;

publicclassBordro{
Vector<Memur>çalışanlar=newVector<Memur>();
...
doubletoplamÖdeme=0;
for(Memurçalışan:çalışanlar)
toplamÖdeme+=çalışan.gelir();
...
}// Bordro sınıfının sonu

Gerçekleştirme Yoluyla Çokbiçimlilik ve Dinamik İletim

[değiştir|kaynağı değiştir]

Java, türleri (sınıflar vearayüzler)gibi olmakilişkisine göre bir sıradüzenine koyan kalıtlama ilişkisinin yanı sıra sınıfları sahip oldukları ortak arayüzlere göre kategorize eden gerçekleştirme ilişkisini de sunar. Gerçekleştirme ilişkisi yoluyla dinamik iletimin kullanılması ve metotların çokbiçimli bir şekilde kullanılması, birbirleriyle benzer olsun veya olmasın, aynı kategoriye giren sınıfların ortak bir arayüzü gerçekleştirmesi ile mümkün olur.

Öğrenci.java
packageöğrenciişleri;

publicclassÖğrenciimplementsComparable<Öğrenci>{
...
pubicintcompareTo(Öğrencisağ){...}
...
}// Öğrenci sınıfının sonu
Vatandaş.java
packagegelirvergisi;

publicclassVatandaşimplementsComparable<Vatandaş>{
...
publicintcompareTo(Vatandaşsağ){...}
...
}// Vatandaş sınıfının sonu
Algoritmalar.java
packagealgoritmalar;

importjava.util.*;

publicclassSıralamalar{
...
publicstatic<VextendsComparable<?extendsV>>voidkabarcık(List<V>kap){
if(kap.length<=1)return;

booleantakasVar=false;
intgeçiş=1;
do{
takasVar=false;
for(intj=0;j<kap.length-geçiş;j++){
VoAnki=kap.get(j),sonraki=kap.get(j+1);
if(oAnki.compareTo(sonraki)>0){
Vgeçici=oAnki;
oAnki=sonraki;
sonraki=geçici;
takasVar=true;
}// if (oAnki.compareTo(sonraki) > 0) sonu
}// for (int j = 0; j < kap.length - geçiş; j++) sonu
}while(++geçiş<kap.length&&takasVar);
}// <V extends Comparable<V>> void kabarcık(List<V>) sonu
...
}// Sıralamalar sınıfının sonu
AlgoritmaSınama.java
importgelirvergisi;
importöğrenciişleri;
import staticalgoritmalar.Sıralamalar;

publicclassAlgoritmaSınama{
...
kabarcık(öğrenciler);
...
kabarcık(vergiMükellefleri);
...
}// AlgoritmaSınama sınıfının sonu

Fonksiyonel programlama dillerinden olanScheme'de dinamik iletim, altyordamların birinci sınıf muamele görmesi nedeniyle oldukça kolay sağlanır. Altyordam türlerinin varlığı, altyordamların argüman olarak geçirilmesini ve altyordamlardan sonuç olarak döndürülmesini olanaklı kılar. Bunun sonucunda, çokbiçimli davranması beklenen altyordama değişik altyordamların geçirilmesi işimizi görecektir. Örneğin, aşağıdaki kabarcık sıralaması gerçekleştirimine ikinci argüman olarak>geçirilmesi ilk argümandaki sayı dizisinin artan sırada sıralanması sağlarken,string-<geçirilmesi ilk argümandaki karakter katarı dizisinin azalan sırada sıralanmasını sağlayacaktır.

(define(kabarcık-algdzöncemi?)
(define(eleman-takasdzij)
(let([geçici(vector-refdzi)])
(vector-set!dzi(vector-refdzj))
(vector-set!dzjgeçici)))
(define(geçişub)
(do((i0(+i1))(takas?#f))
((=i(-ub1))takas?)
(when(öncemi?(vector-refdz(+i1))(vector-refdzi))
(eleman-takasdzi(+i1))
(set!takas?#t))))

(do((j(vector-lengthdz)(-j1))
(takas?#t(geçişj)))
((or(nottakas?)(=j1))dz)))
  1. ^Adres işlecinin (&) kullanımlardan birinde olup diğerinde olmaması sizi şaşırtmasın. Her iki durumda da geçirilen değer, söz konusu fonksiyonun başlangıç adresini işaret eden bir gösterici değeri olacaktır.
  2. ^Gerçekleştirimi sağlanmayan dinamik iletimli bir fonksiyonunun bulunması,Memursınıfını birsoyut sınıf(İngilizce:abstract class) yapıyor. Dolayısıyla, kabımız içindeki referanslarınMemurnesnelerini göstermesi, soyut bir sınıfın nesneleri yaratılamayacağı için, söz konusu olmayacaktır.

Ayrıca bakınız

[değiştir|kaynağı değiştir]

Dış bağlantılar

[değiştir|kaynağı değiştir]