Geri arama işlevi nedir?


685

Geri arama işlevi nedir?


8
burada bulabilirsiniz: stackoverflow.com/a/9652434/3343174 geri aramalar hakkında en iyi açıklama
Fakher


Ayrıntılı açıklama için ikinci cevaba bakınız
Donato

Şimdiye kadar bulduğum geri
Sameer Sinha

Yanıtlar:


682

Geliştiriciler genellikle lanet olası şeyin adı nedeniyle geri arama ne olduğu ile karıştırılır.

Geri arama işlevi, aşağıdakiler olan bir işlevdir:

  • başka bir işlev tarafından erişilebilir ve
  • ilk işlev tamamlanırsa ilk işlevden sonra çağrılır

Bir geri çağırma işlevinin nasıl çalıştığını hayal etmenin güzel bir yolu, bu işlevin aktarıldığı işlevin " arka tarafında " olarak adlandırılan bir işlev olmasıdır .

Belki daha iyi bir isim "sonradan ara" işlevi olabilir.

Bu yapı, önceki bir etkinlik tamamlandığında bir etkinliğin gerçekleşmesini istediğimiz eşzamansız davranışlar için çok kullanışlıdır.

pseudocode:

// A function which accepts another function as an argument
// (and will automatically invoke that function when it completes - note that there is no explicit call to callbackFunction)
funct printANumber(int number, funct callbackFunction) {
    printout("The number you provided is: " + number);
}

// a function which we will use in a driver function as a callback function
funct printFinishMessage() {
    printout("I have finished printing numbers.");
}

// Driver method
funct event() {
   printANumber(6, printFinishMessage);
}

Event () öğesini çağırdıysanız sonuç:

The number you provided is: 6
I have finished printing numbers.

Buradaki çıktının sırası önemlidir. Geri arama işlevleri daha sonra çağrıldığından, ilk olarak değil, "Yazdırma numaralarını bitirdim" en son yazdırılır.

Geri aramalar, işaretçi dilleriyle kullanımları nedeniyle adlandırılır. Bunlardan birini kullanmazsanız, 'geri arama' adı üzerinde çalışmayın. Başka bir yönteme argüman olarak sağlanan bir yöntemi açıklamanın sadece bir ad olduğunu anlayın, böylece üst yöntem çağrıldığında (düğme tıklaması, bir zamanlayıcı onaylaması gibi herhangi bir koşul) ve yöntem gövdesi tamamlandığında, sonra geri arama işlevi çağrılır.

Bazı diller, birden çok geri çağırma işlevi bağımsız değişkeninin desteklendiği yapıları destekler ve üst işlevin nasıl tamamlandığına bağlı olarak çağrılır (örneğin, ana işlevin başarıyla tamamlanması durumunda bir geri çağrı çağrılır, üst işlevin bir özel hata, vb.).


31
Örneğiniz harika ama terminolojinin neden "geri arama" olduğunu anlamıyorum. AnlamıOfLife ne zaman "geri çağırılır"?
CodyBugstein

4
Merhaba, hakkında once its parent method completes, the function which this argument represents is then called. Fonksiyonu gibi üst işlevinin çalışma zamanı ortasından argüman olarak başka bir işleve geçirilen ancak denir Yani parent(cb) {dostuff1(); cb(); dostuff2()}bu bir kabul edilmez sonra callbackişlev?
Max Yari

2
@MaxYari: IMHO, hala geri arama olarak kabul ediliyor.Burada önemli olan, ana işlevin bir şekilde giriş işlevini (aka geri arama) kullanmasıdır. Ortada veya sonunda veya bir koşulun karşılanması durumunda çağrılabilir.
Kamran Bigdely

12
@ 8bitjunkie teşekkür ederim - ama printANumber işlevi içinde anlamOfLife yöntemi nerede çağrılır?
BKSpurgeon

2
Bu hiç doğru değil: "ilk işlev tamamlandıktan sonra otomatik olarak çağrılır". Otomatik olarak bırakılmaksızın, geri arama yapmak zorunda değildir. Aslında, üst işlev tamamlanmadan geri aramaların tamamlanması nadir değildir. Ben insanların geri çağrıları "daha sonra" yürütülen işlevler olarak nasıl tarif sevmiyorum. Onları öğrenen insanlar için çok kafa karıştırıcı. Basitçe söylemek gerekirse, geri çağrılar sadece diğer işlevlere argüman olarak iletilen işlevlerdir. Dönemi. Daha iyi bir açıklama, NEDEN işlev referansları üzerindeki geri çağrıların açıklanmasını içerir.
Ürdün

226

Opak Tanımı

Geri arama işlevi, başka bir kod parçasına sağladığınız ve bu kod tarafından çağrılmasını sağlayan bir işlevdir.

Onaylanmış örnek

Bunu neden yapmak istiyorsun? Diyelim ki çağırmanız gereken bir hizmet var. Hizmet hemen geri dönerse, şunları yaparsınız:

  1. Bunu aramak
  2. Sonucu bekle
  3. Sonuç geldiğinde devam et

Örneğin, hizmetin factorialişlev olduğunu varsayalım . Değerini 5!istediğinizde çağırırsınız factorial(5)ve aşağıdaki adımlar gerçekleşir:

  1. Geçerli yürütme konumunuz kaydedilir (yığına, ancak bu önemli değil)

  2. Yürütme, factorial

  3. Ne zaman factorialtamamlamalar, bu sonuca koyar bir yerde binebilirsek

  4. İcra, bulunduğu yere geri döner [1]

Diyelim ki factorialçok uzun zaman aldı, çünkü ona büyük sayılar veriyorsunuz ve bir yerde süper hesaplama kümesinde çalışması gerekiyor. Diyelim ki sonucunuzun geri gelmesi 5 dakika sürüyor. Yapabilirdin:

  1. Tasarımınızı koruyun ve uyurken gece programınızı çalıştırın, böylece ekranın yarısına bakmıyorsunuz

  2. factorialYaparken başka şeyler yapmak için programınızı tasarlayın

İkinci seçeneği seçerseniz, geri aramalar sizin için işe yarayabilir.

Uçtan uca tasarım

Bir geri arama modelinden yararlanmak için, istediğiniz factorialşekilde aşağıdaki şekilde arama yapabilirsiniz :

factorial(really_big_number, what_to_do_with_the_result)

İkinci parametre,, geri göndermeden önce sonucuna çağıracağı umuduyla what_to_do_with_the_resultbirlikte gönderdiğiniz bir işlevdir .factorialfactorial

Evet, bu, factorialgeri çağrıları desteklemek için yazılmış olması gerektiği anlamına gelir .

Şimdi geri aramalarınıza bir parametre iletmek istediğinizi varsayalım. Şimdi yapamazsınız, çünkü onu aramayacaksınız factorial. Bu nedenle factorial, parametrelerinizi iletmenize izin vermek için yazılması gerekir ve çağırdığında bunları geri aramanıza iletir. Şöyle görünebilir:

factorial (number, callback, params)
{
    result = number!   // i can make up operators in my pseudocode
    callback (result, params)
}

Şimdi factorialbu kalıba izin veriyor, geri aramanız şöyle görünebilir:

logIt (number, logger)
{
    logger.log(number)
}

ve aramanız factorialolacaktır

factorial(42, logIt, logger)

Ya bir şeyi geri döndürmek istiyorsan logIt? Yapamazsınız, çünkü factorialbuna dikkat etmiyor.

Peki, neden factorialgeri aramalarınızın geri döndüğünü geri veremiyorsunuz ?

Engellememesi

Yürütme işlemi factorialbittiğinde geri aramaya verilmesi gerektiği için, gerçekten arayanına hiçbir şey döndürmemelidir. Ve ideal olarak, bir şekilde çalışmasını başka bir iş parçacığında / işlemde / makinede başlatır ve hemen geri dönebilir, böylece devam edebilirsiniz, belki böyle bir şey:

factorial(param_1, param_2, ...)
{
    new factorial_worker_task(param_1, param_2, ...);
    return;
}

Bu artık "eşzamansız bir çağrı" dır, yani onu aradığınızda hemen geri döner ancak henüz işini gerçekten yapmamıştır. Bu yüzden, onu kontrol etmek ve bittiğinde sonucunu elde etmek için mekanizmalara ihtiyacınız var ve programınız süreçte daha karmaşık hale geldi.

Bu arada, bu kalıbı kullanarak factorial_worker_taskgeri çağrınızı eşzamansız olarak başlatabilir ve hemen geri dönebilirsiniz.

Ee ne yapıyorsun?

Cevap, geri arama modeli içinde kalmaktır. Ne zaman yazmak istersen

a = f()
g(a)

ve feşzamansız olarak çağrılmak yerine,

f(g)

nerede ggeri arama olarak geçirilir.

Bu, programınızın akış topolojisini temelden değiştirir ve alışmak biraz zaman alır.

Programlama diliniz, anında işlevler oluşturmanıza olanak tanıyarak size çok yardımcı olabilir. Yukarıdaki kodda, işlev gkadar küçük olabilir print (2*a+1). Eğer diliniz bunu tamamen gereksiz bir isim ve imzayla ayrı bir işlev olarak tanımlamanızı gerektiriyorsa, bu deseni çok kullanırsanız hayatınız hoşlanmaz.

Öte yandan, diliniz lambdalar oluşturmanıza izin veriyorsa, o zaman çok daha iyi durumdasınız demektir. Sonunda böyle bir şey yazacaksın

f( func(a) { print(2*a+1); })

ki bu çok daha hoş.

Geri arama nasıl iletilir

Geri arama işlevini nasıl iletirsiniz factorial? Bunu birkaç şekilde yapabilirsiniz.

  1. Aranan işlev aynı işlemde çalışıyorsa, bir işlev işaretçisi iletebilirsiniz

  2. Ya da belki fn name --> fn ptrprogramınızda bir sözlük tutmak istersiniz , bu durumda adı geçebilirsiniz

  3. Belki de diliniz, yerinde lambda olarak mümkün olan işlevi tanımlamanıza izin verir! Dahili olarak bir tür nesne yaratıyor ve bir işaretçi geçiriyor, ancak bunun için endişelenmenize gerek yok.

  4. Belki de aradığınız işlev tamamen ayrı bir makinede çalışıyor ve HTTP gibi bir ağ protokolü kullanarak çağırıyorsunuz. Geri aramanızı HTTP tarafından çağrılabilir bir işlev olarak gösterebilir ve URL'sini iletebilirsiniz.

Kaptın bu işi.

Geri aramaların son yükselişi

Girdiğimiz bu web çağında, çağırdığımız hizmetler genellikle ağ üzerinden gerçekleşiyor. Genellikle bu hizmetler üzerinde herhangi bir kontrole sahip değiliz, yani bunları yazmadık, bakımını yapmıyoruz, bunların çalışmasını veya nasıl performans gösterdiğini garanti edemeyiz.

Ancak bu hizmetlerin yanıt vermesini beklerken programlarımızın engellenmesini bekleyemeyiz. Bunun farkında olarak, servis sağlayıcılar genellikle geri arama modelini kullanarak API'ler tasarlar.

JavaScript, lambdas ve kapaklar gibi geri çağrıları çok güzel bir şekilde destekler. JavaScript dünyasında hem tarayıcıda hem de sunucuda çok fazla etkinlik var. Mobil cihazlar için geliştirilen JavaScript platformları bile var.

İlerledikçe, gittikçe daha fazla, bu anlayışın gerekli olacağı asenkron kod yazacağız.


1
Çok iyi açıklanmış bir konsept ..! :)
piyushGoyal

Harika bir açıklama, +1.
Lingamurthy CS

1
Diğerleri arasında en iyi cevap budur. Nazikçe oy verin.
Abhishek Nalin

3
Mükemmel açıklanır ve her şey açıklanır. Keşke tekrar değerlendirebilsem.
Yogesh Yadav

Evet lambas'ın javascript ve ruby'de nasıl çalıştığını anlıyorum. Ve java 8 ama java'nın eski sürümleri lambas kullanmadı ve bunun yerine sınıfları kullandı ve bu tür geri aramaların nasıl çalıştığını bilmek istiyorum. Hala diğerine üstün bir cevap.
Donato

97

Geri aramanın tek bir kelime olduğunu unutmayın.

Vikipedi geri arama sayfası bunu çok iyi açıklıyor.

wikipedia sayfasından alıntı:

Bilgisayar programlamasında geri arama, diğer koda argüman olarak iletilen yürütülebilir koda veya yürütülebilir kodun bir başvurusudur. Bu, daha düşük seviyeli bir yazılım katmanının daha yüksek seviyedeki bir katmanda tanımlanan bir alt programı (veya işlevi) çağırmasını sağlar.


14
Yanıt vermenin güzel bir yolu.
Chathuranga Chandrasekara

1
Bu da cevaba farklı bir şekilde yol açar. "Geri arama" adı, "geri" çağrılmış, aynı şekilde kapatma işleminden geçmiş bir şey kapatılmış ve oturum açmak için kullanılan bir şey bir oturum açmadır.
İsimsiz

22
Bu bir yorum olabilirdi - temelde Wikipedia'ya bir bağlantı
CodyBugstein

Vikipedi, gerçekten çok ilginç programlama şeyleri var. Ben her zaman "geri arama" terimi en iyi "Ben geri arayacağım ..." ifadesini kullanarak açıklanmış gibi hissettim
Thomas

Javascriptissexy.com/… 'de büyük açıklama; ki burada tekrar yayınlayacağım; Geri arama işlevi, başka bir işleve parametre olarak iletilen bir işlevdir ve geri arama işlevi, otherFunction içinde çağrılır veya yürütülür. // click yönteminin parametresindeki öğenin bir değişken değil bir işlev olduğunu unutmayın. // Öğe, bir geri arama işlevidir $ ("# btn_1"). (Function () {alert ("Btn 1 Clicked") );}); Önceki örnekte gördüğünüz gibi, bir işlevi yürütmek için tıklama yöntemine bir parametre olarak
geçiriyoruz

46

Layman yanıtı, sizin tarafınızdan değil, belirli bir olay gerçekleştikten sonra veya bir kod işlendikten sonra kullanıcı veya tarayıcı tarafından çağrılan bir işlevdir.


42

Geri arama işlevi, belirli bir koşul gerçekleştiğinde çağrılması gereken işlevdir. Hemen geri çağrılmak yerine, geri arama işlevi gelecekte belirli bir noktada çağrılır.

Genellikle eşzamansız olarak bitecek bir görev başlatıldığında kullanılır (yani, çağrı işlevi döndükten bir süre sonra sona erer).

Örneğin, bir web sayfası isteme eden bir işlev, arayan kişinin web sayfasının indirilmesi bittiğinde çağrılacak bir geri arama işlevi sağlamasını gerektirebilir.


İlk cümlenizde söylüyorsunuz "...when a condition is met"ama üst işlev yürütmeyi bitirdiğinde ve koşullara (?) Bağlı olmadığında geri aramaların çağrıldığını düşündüm.
Ojonugwa Jude Ochalifu

'Belli koşul' sadece rastgele olmaktan ziyade bir sebepten dolayı çağrıldıkları anlamına gelir. Ebeveyn / içerik oluşturucu hâlâ yürütülürken geri çağrı yapılabilir - bu, programcı beklemiyorsa bir yarış durumuna neden olabilir.
Thomas Bratt

Açıklama için teşekkürler
Ojonugwa Jude Ochalifu

34

Geri aramalar, telefon sistemi açısından en kolay tanımlanır. İşlev çağrısı, birini telefonla aramaya, ona bir soru sormaya, bir cevap almaya ve telefonu kapatmaya benzer; bir geri arama eklemek benzetmeyi değiştirir, böylece ona bir soru sorduktan sonra, ona adınızı ve numaranızı da verirsiniz, böylece sizi cevapla geri arayabilir.

- Paul Jakubik, "C ++ 'da Geri Arama Uygulamaları"


1
Yani ismim ve numaram bir fonksiyon mu?
Koray Tugay

Hayır, "geri arama" bunun yerine iyi bir ad olsaydı benzetme olurdu: telefon operatörünün arama yapmasını istersiniz. Son.
gherson

33

Bu "geri arama" jargonunun birçok yerde yanlışlıkla kullanılmış olduğuna inanıyorum. Benim tanımım şöyle bir şey olurdu:

Geri arama işlevi, birisine ilettiğiniz ve belirli bir zamanda onu aramasına izin verdiğiniz bir işlevdir.

Bence insanlar wiki tanımının ilk cümlesini okudular:

geri arama, diğer koda argüman olarak iletilen yürütülebilir koda başvuru veya yürütülebilir bir kod parçasıdır.

Çok sayıda API ile çalışıyorum, çeşitli kötü örneklere bakın. Birçok kişi bir işlev işaretçisi (çalıştırılabilir koda başvuru) veya anonim işlevleri (bir çalıştırılabilir kod parçası) "geri arama" olarak adlandırılır.

Aslında wiki tanımındaki sadece ikinci cümle, bir geri çağırma işlevi ile normal bir işlev arasındaki farkları gösterir:

Bu, daha düşük seviyeli bir yazılım katmanının daha yüksek seviyedeki bir katmanda tanımlanan bir alt programı (veya işlevi) çağırmasını sağlar.

bu yüzden fark, fonksiyonu kimin geçeceği ve fonksiyona nasıl geçeceğinizdir. Bir işlevi tanımlayıp başka bir işleve geçirirseniz ve doğrudan bu işlev gövdesinde çağırırsanız, bu işlevi geri arama olarak adlandırmayın. Tanımda, geçtiğiniz işlev "alt düzey" işlevi olarak adlandırılacaktır.

Umarım insanlar bu kelimeyi belirsiz bağlamda kullanmayı bırakabilirler, bu sadece insanların daha iyi anlamalarına yardımcı olamaz.


2
Cevabınız mantıklı ... ama bunu hayal etmekte zorlanıyorum. Bir örnek verebilir misin?
CodyBugstein

3
@Zane Wong :: Son olarak, "Tanımda geçtiğiniz fonksiyonun" alt seviye "fonksiyonu tarafından aranacağını söylüyor." Daha düşük seviyeli fonksiyonun ne ifade ettiğini açıklayabilir misiniz? Bir örnek verirseniz daha iyi olur.
Viku

Bir örnek güzel olurdu
Yusuf Azad

1
Klasik işlev çağrısı ve geri arama stili arasındaki farkın dependy yönüne bağlantı olduğunu düşünüyorum: A modülü B modülüne ("kullanır") bağlıysa, A B işlevini çağırır, bu bir geri arama değildir. A, işlevine bir başvuru B'ye iletirse, B, A'nın bir işlevini çağırırsa, bu bir geri çağrıdır: çağrı, modül bağımlılığına kıyasla geriye doğru gider.
XouDo

30

Basit tutalım. Geri arama işlevi nedir?

Parable ve Analogy'den Örnek

Bir sekreterim var. Her gün ondan: (i) firmanın postaneye giden postasını bırakmasını ve bunu yaptıktan sonra şunları yapmasını isterim: (ii) bu yapışkan notlardan birinde ona yazdığım herhangi bir görev .

Şimdi, yapışkan notun görevi nedir? Görev günden güne değişir.

Diyelim ki bu gün, bazı belgeleri yazdırmasını istiyorum. Bu yüzden yapışkan not üzerine yazıyorum ve yayınlaması gereken giden posta ile birlikte masasına sabitliyorum.

Özetle:

  1. önce, postayı bırakması gerekiyor ve
  2. Bundan hemen sonra , bazı belgeleri yazdırması gerekiyor.

Geri arama işlevi ikinci görevdir: bu belgelerin yazdırılması. Çünkü posta bırakıldıktan SONRA yapılır ve ayrıca dokümanı yazdırmasını söyleyen yapışkan not, göndermesi gereken posta ile birlikte ona verilir.

Şimdi bunu programlama kelime dağarcığına bağlayalım

  • Bu durumda yöntem adı: DropOffMail.
  • Ve geri arama işlevi: PrintOffDocuments. PrintOffDocuments geri arama işlevidir, çünkü sekreterin bunu sadece DropOffMail çalıştırıldıktan sonra yapmasını istiyoruz.
  • Yani "pass: PrintOffDocuments" DropOffMail yöntemine "argüman" olarak. Bu önemli bir nokta.

Hepsi bu kadar. Başka bir şey yok. Umarım bu sizin için temizlenir - ve değilse, bir yorum gönderin ve açıklığa kavuşturmak için elimden geleni yapacağım.


18

Bu, yöntemlerin sonunda geri çağrıları return ifadeleri gibi gösterir.

Onların ne olduğundan emin değilim.

Bence geri çağrılar aslında başka bir işlevin çağrılması ve tamamlanması sonucunda bir işleve çağrıdır.

Ben de geri aramaların menşeli çağrıyı ele almayı amaçladığını düşünüyorum.


1
Geri aramalar ile Geri dönüş ifadelerinin sorgulanması için +1. Eskiden buna yakalanırdım ve birlikte çalıştığım birçok mezun da.
8bitjunkie

2
İyi cevap - diğer cevapların çoğunun aksine anlamama yardımcı oldu!
adaam

18

Nedir geri arama ?

  • Genel olarak, birisinin aldığını iade etmek için yapılan bir telefon görüşmesi.
  • Hesaplamada geri arama , diğer koda argüman olarak iletilen yürütülebilir kod parçasıdır. İşlev çalışmasıyla (veya bir olay meydana geldiğinde) tamamlandığında, geri aramanızı (sizi geri çağırır - dolayısıyla adı) çağırır.

Bir nedir geri arama fonksiyonu ?

  • geri arama işlevi, bir görevi tamamladığında Efendisine "geri çağrı" yapan bir Hizmetkar gibidir.
  • Bir geri arama işlevi (en, bu başka bir fonksiyonu diyelim başka bir işleve bir fonksiyonu olan otherFunctionbir parametre olarak), ve geri arama fonksiyonu içinde denir (veya yürütülen) olup otherFunction.
    function action(x, y, callback) {
        return callback(x, y);
    }

    function multiplication(x, y) {
        return x * y;
    }

    function addition(x, y) {
        return x + y;
    }

    alert(action(10, 10, multiplication)); // output: 100

    alert(action(10, 10, addition)); // output: 20

SOA'da geri arama, Eklenti Modüllerinin kaptan / ortamdan hizmetlere erişmesine izin verir.

Analoji: Geri aramalar. Asenkron. Engellemeyen
gerçek geri arama örneği


Geri arama işlevinin kendisi daha üst düzey bir işlev değildir. Üst düzey bir işleve geçirilir.
danio

17

Sonra Arama aptal adından daha iyi bir isim olacaktır, geri arama . Bir işlev içinde koşul sağlandığında veya karşılaşıldığında, bağımsız değişken olarak alınan başka bir işlevi, Sonra Ara işlevini çağırın .

Bir işlev içindeki bir iç işlevi sabit kodlamak yerine, önceden yazılmış bir Call After işlevini bağımsız değişken olarak kabul etmek için bir işlev yazar . Sonra Çağrı devlet değişikliklere dayanarak denilen olsun olabilir argüman alan işlevindeki kod tarafından tespit edildi.


Bu harika bir fikir. Bunu denemek ve açıklamak için "arkada denilen" için gittim. Martin Fowler gibi birisinin seminal blog'unda "sonra çağır" ı yeni bir terim olarak popülerleştirdiğini görebiliyordum.
8bitjunkie

15

Geri arama işlevi, bir eylem tamamlandığında çağrılacak, ek işleme vb. Gerektiren mevcut bir işleve / yönteme belirttiğiniz bir işlevdir.

Örneğin, Javascript'te veya daha spesifik olarak jQuery'de, bir animasyon bittiğinde çağrılacak bir geri çağrı argümanı belirtebilirsiniz.

PHP'de bu preg_replace_callback()işlev, normal ifade eşleştirildiğinde çağrılacak ve argüman olarak eşleştirilen dizeleri geçirecek bir işlev sağlamanıza olanak tanır.


10

resme bak :)bu nasıl çalışır

Ana program geri çağırma işlevi adıyla kütüphane işlevini (sistem düzeyi işlevi de olabilir) çağırır. Bu geri arama işlevi birden çok şekilde uygulanabilir. Ana program, gereksinime göre bir geri arama seçer.

Son olarak, kütüphane işlevi yürütme sırasında geri arama işlevini çağırır.


7
Buna bir metin açıklaması da eklemek ister misiniz ? Görüntü kaybolursa, bu cevap tüm içeriği kaybeder.
Tim Post

diğer insanlardan gelen metin bunu en iyi şekilde açıklar. hissettiğim tek şey eksik görüntü :)

Burada gördüğüm tüm uzun soluklu açıklamalar arasında bu beni "ahhhhh, şimdi onun kullanımını görüyorum". Bir oy verin.
DiBosco

7

Bu sorunun basit cevabı, bir geri çağırma işlevinin, bir işlev işaretçisi aracılığıyla çağrılan bir işlev olmasıdır. Bir işlevin işaretçisini (adresini) başka bir değişkene argüman olarak iletirseniz, bu işaretçi işlevi çağırmak için kullanıldığında işaret ettiği bir geri arama yapıldığı söylenir.


7

sort(int *arraytobesorted,void (*algorithmchosen)(void))Bir işlev işaretçisini argümanı olarak kabul edebileceği bir işleve sahip olduğumuzu varsayalım sort(). Ardından, burada işlev işaretçisi tarafından adreslenen koda geri arama işlevialgorithmchosen denir .

Ve avantajı görmek gibi bir algoritma seçebilirsiniz:

  1.    algorithmchosen = bubblesort
  2.    algorithmchosen = heapsort
  3.    algorithmchosen = mergesort   ...

Diyelim ki prototip ile uygulandı:

  1.   `void bubblesort(void)`
  2.   `void heapsort(void)`
  3.   `void mergesort(void)`   ...

Nesneye Yönelik Programlamada Çok Biçimlilik Sağlamada Kullanılan Bir Kavram


Javascriptissexy.com/… 'de büyük açıklama; ki burada tekrar yayınlayacağım; Geri arama işlevi, başka bir işleve parametre olarak iletilen bir işlevdir ve geri arama işlevi, otherFunction içinde çağrılır veya yürütülür. // click yönteminin parametresindeki öğenin bir değişken değil bir işlev olduğunu unutmayın. // Öğe, bir geri arama işlevidir $ ("# btn_1"). (Function () {alert ("Btn 1 Clicked") );}); Önceki örnekte gördüğünüz gibi, bir işlevi yürütmek için tıklama yöntemine parametre olarak
geçiriyoruz

4

“Bilgisayar programlamasında geri arama, diğer koda argüman olarak iletilen yürütülebilir koda ya da yürütülebilir koda bir referanstır. Bu, daha düşük seviyeli bir yazılım katmanının, daha yüksek seviyedeki bir katmanda tanımlanan bir alt programı (veya işlevi) çağırmasını sağlar. ” - Wikipedia

İşlev İşaretçisi'ni kullanarak C'de geri arama

C'de geri arama İşlev İşaretçisi kullanılarak gerçekleştirilir. İşlev İşaretçisi - adından da anlaşılacağı gibi, bir işlevin işaretçisidir.

Örneğin, int (* ptrFunc) ();

Burada, ptrFunc argüman almayan ve bir tamsayı döndüren bir fonksiyonun göstergesidir. Parantez içine almayı unutmayın, aksi takdirde derleyici hiçbir şey almayan ve bir tamsayıya bir işaretçi döndüren normal bir işlev adı olduğunu varsayar.

İşlev işaretçisini göstermek için bazı kodlar.

#include<stdio.h>
int func(int, int);
int main(void)
{
    int result1,result2;
    /* declaring a pointer to a function which takes
       two int arguments and returns an integer as result */
    int (*ptrFunc)(int,int);

    /* assigning ptrFunc to func's address */                    
    ptrFunc=func;

    /* calling func() through explicit dereference */
    result1 = (*ptrFunc)(10,20);

    /* calling func() through implicit dereference */        
    result2 = ptrFunc(10,20);            
    printf("result1 = %d result2 = %d\n",result1,result2);
    return 0;
}

int func(int x, int y)
{
    return x+y;
}

Şimdi fonksiyon göstergesini kullanarak C'deki Geri Arama kavramını anlamaya çalışalım.

Tüm programın üç dosyası vardır: callback.c, reg_callback.h ve reg_callback.c.

/* callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* callback function definition goes here */
void my_callback(void)
{
    printf("inside my_callback\n");
}

int main(void)
{
    /* initialize function pointer to
    my_callback */
    callback ptr_my_callback=my_callback;                        
    printf("This is a program demonstrating function callback\n");
    /* register our callback function */
    register_callback(ptr_my_callback);                          
    printf("back inside main program\n");
    return 0;
}

/* reg_callback.h */
typedef void (*callback)(void);
void register_callback(callback ptr_reg_callback);


/* reg_callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* registration goes here */
void register_callback(callback ptr_reg_callback)
{
    printf("inside register_callback\n");
    /* calling our callback function my_callback */
    (*ptr_reg_callback)();                               
}

Bu programı çalıştırırsak, çıktı

Bu, ana programın içindeki my_callback içinde register_callback içinde fonksiyon geri aramasını gösteren bir programdır

Daha yüksek katman işlevi, alt katman işlevini normal arama olarak çağırır ve geri arama mekanizması, alt katman işlevinin, daha yüksek katman işlevini bir işaretçi aracılığıyla geri arama işlevine çağırmasını sağlar.

Arabirimi Kullanarak Java'da Geri Arama

Java işlev işaretçisi kavramına sahip değildir Arayüz mekanizması aracılığıyla Geri Arama mekanizmasını uygular Burada işlev işaretçisi yerine, callee görevini bitirdiğinde çağrılacak bir yönteme sahip bir Arabirim bildiririz

Bir örnekle göstereyim:

Geri Arama Arayüzü

public interface Callback
{
    public void notify(Result result);
}

Arayan veya Üst Seviye Sınıfı

public Class Caller implements Callback
{
Callee ce = new Callee(this); //pass self to the callee

//Other functionality
//Call the Asynctask
ce.doAsynctask();

public void notify(Result result){
//Got the result after the callee has finished the task
//Can do whatever i want with the result
}
}

Callee veya alt katman işlevi

public Class Callee {
Callback cb;
Callee(Callback cb){
this.cb = cb;
}

doAsynctask(){
//do the long running task
//get the result
cb.notify(result);//after the task is completed, notify the caller
}
}

EventListener desenini kullanarak geri arama

  • Liste öğesi

Bu model, belirli bir görevin tamamlandığını 0 ile n arasında sayıda Gözlemci / Dinleyici bildirmek için kullanılır

  • Liste öğesi

Geri arama mekanizması ile EventListener / Observer mekanizması arasındaki fark, geri aramada, arayan kişinin tek bir arayanı bildirmesidir, oysa Eventlisener / Observer'da, arayan kişi o olayla ilgilenen herkesi bilgilendirebilir (bildirim, görevi tetiklemeyen uygulama)

Bir örnekle açıklayayım.

Olay Arayüzü

public interface Events {

public void clickEvent();
public void longClickEvent();
}

Sınıf Widget'ı

package com.som_itsolutions.training.java.exampleeventlistener;

import java.util.ArrayList;
import java.util.Iterator;

public class Widget implements Events{

    ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
    ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();

    @Override
    public void clickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                while(it.hasNext()){
                    OnClickEventListener li = it.next();
                    li.onClick(this);
                }   
    }
    @Override
    public void longClickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
        while(it.hasNext()){
            OnLongClickEventListener li = it.next();
            li.onLongClick(this);
        }

    }

    public interface OnClickEventListener
    {
        public void onClick (Widget source);
    }

    public interface OnLongClickEventListener
    {
        public void onLongClick (Widget source);
    }

    public void setOnClickEventListner(OnClickEventListener li){
        mClickEventListener.add(li);
    }
    public void setOnLongClickEventListner(OnLongClickEventListener li){
        mLongClickEventListener.add(li);
    }
}

Sınıf Düğmesi

public class Button extends Widget{
private String mButtonText;
public Button (){
} 
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}

Sınıf Onay Kutusu

public class CheckBox extends Widget{
private boolean checked;
public CheckBox() {
checked = false;
}
public boolean isChecked(){
return (checked == true);
}
public void setCheck(boolean checked){
this.checked = checked;
}
}

Etkinlik Sınıfı

paket com.som_itsolutions.training.java.exampleeventlistener;

public class Activity implements Widget.OnClickEventListener
{
    public Button mButton;
    public CheckBox mCheckBox;
    private static Activity mActivityHandler;
    public static Activity getActivityHandle(){
        return mActivityHandler;
    }
    public Activity ()
    {
        mActivityHandler = this;
        mButton = new Button();
        mButton.setOnClickEventListner(this);
        mCheckBox = new CheckBox();
        mCheckBox.setOnClickEventListner(this);
        } 
    public void onClick (Widget source)
    {
        if(source == mButton){
            mButton.setButtonText("Thank you for clicking me...");
            System.out.println(((Button) mButton).getButtonText());
        }
        if(source == mCheckBox){
            if(mCheckBox.isChecked()==false){
                mCheckBox.setCheck(true);
                System.out.println("The checkbox is checked...");
            }
            else{
                mCheckBox.setCheck(false);
                System.out.println("The checkbox is not checked...");
            }       
        }
    }
    public void doSomeWork(Widget source){
        source.clickEvent();
    }   
}

Diğer Sınıf

public class OtherClass implements Widget.OnClickEventListener{
Button mButton;
public OtherClass(){
mButton = Activity.getActivityHandle().mButton;
mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
}
@Override
public void onClick(Widget source) {
if(source == mButton){
System.out.println("Other Class has also received the event notification...");
}
}

Ana sınıf

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Activity a = new Activity();
OtherClass o = new OtherClass();
a.doSomeWork(a.mButton);
a.doSomeWork(a.mCheckBox);
}
}

Yukarıdaki koddan da görebileceğiniz gibi, temelde uygulamamız için olabilecek tüm olayları listeleyen olaylar adında bir arayüze sahibiz. Widget sınıfı, Button, Checkbox gibi tüm UI bileşenleri için temel sınıftır. Bu kullanıcı arabirimi bileşenleri, olayları çerçeve kodundan gerçekten alan nesnelerdir. Widget sınıfı Olaylar arabirimini uygular ve ayrıca OnClickEventListener ve OnLongClickEventListener adlı iki iç içe arabirim vardır

Bu iki arayüz, Düğme veya Onay Kutusu gibi Widget'tan türetilen UI bileşenlerinde meydana gelebilecek olayları dinlemekten sorumludur. Dolayısıyla, bu örneği Java Arayüzü kullanan önceki Geri Arama örneğiyle karşılaştırırsak, bu iki arabirim Geri Arama arabirimi olarak çalışır. Böylece daha yüksek seviye kodu (Here Activity) bu iki arayüzü uygular. Bir widget'ta her olay gerçekleştiğinde, daha yüksek düzey kodu (veya burada Etkinlik olan üst düzey kodda uygulanan bu arabirimlerin yöntemi) çağrılır.

Şimdi Callback ve Eventlistener kalıbı arasındaki temel farkı tartışalım. Daha önce de belirttiğimiz gibi, Callee sadece bir Arayanı bilgilendirebilir. Ancak EventListener örneği söz konusu olduğunda, Uygulamanın herhangi bir kısmı veya sınıfı Düğme veya Onay Kutusunda meydana gelebilecek olaylara kaydolabilir. Bu tür bir sınıf örneği OtherClass'tır. OtherClass kodunu görürseniz, etkinlikte tanımlanan Düğmede oluşabilecek ClickEvent öğesini dinleyici olarak kaydettiğini görürsünüz. İlginç olan kısım, Etkinliğin (Arayan) yanı sıra, Düğme üzerinde tıklama olayı gerçekleştiğinde bu Diğer Sınıfın da bilgilendirilmesidir.


Lütfen yalnızca bağlantı yanıtlarından kaçının . "Harici bir siteye link ancak daha fazla” olan Cevapları silinebilir .
Quentin

3

Geri arama işlevi, belirli bir işleve veya nesneye ilettiğiniz (başvuru veya işaretçi olarak) bir işlevdir. Bu işlev veya nesne, bu işlevi herhangi bir zamanda, muhtemelen birden çok kez, herhangi bir amaç için geri çağırır:

  • görevin sonunu bildirme
  • iki öğe arasında karşılaştırma isteğinde bulunma (c qsort () gibi)
  • bir sürecin ilerlemesini raporlama
  • olayları bildirme
  • bir nesnenin somutlaştırılmasını devretme
  • bir alanın resmini devretmek

...

Bu nedenle, geri aramayı başka bir işlevin veya görevin sonunda çağrılan bir işlev olarak tanımlamak aşırı derecede basitleştiricidir (yaygın bir kullanım durumu olsa bile).


2

Geri arama, bir işlevi bir parametre olarak başka bir işleve geçirme fikridir ve işlem tamamlandığında bu işlevin çağrılmasını sağlar.

Geri arama kavramını yukarıdaki harika cevaplarla alırsanız, fikrinin arka planını öğrenmenizi öneririz.

"Onları (Bilgisayar-Bilimciler) geri arama geliştirmeye iten nedir?" Engellenen bir sorun öğrenebilirsiniz. (Özellikle kullanıcı arayüzünü engelleme) Ve geri çağrı bunun tek çözümü değildir. Birçok başka çözüm var (ör: Thread, Futures, Promises ...).


1

Önemli kullanım alanlarından biri, işlevinizden birini tanıtıcı (yani geri arama) olarak kaydetmeniz ve ardından bir iş veya işlem yapmak için bir ileti göndermeniz / bazı işlevleri çağırmanızdır. İşlem tamamlandıktan sonra, çağrılan fonksiyon kayıtlı fonksiyonumuzu arayacaktır (yani şimdi geri arama yapılıyor), böylece işlemin yapıldığını gösterir.
Bu wikipedia bağlantısı grafik olarak oldukça iyi açıklıyor.


1

Üst düzey işlev olarak da bilinen geri çağrı işlevi, başka bir işleve parametre olarak iletilen bir işlevdir ve geri çağırma işlevi üst işlev içinde çağrılır (veya yürütülür).

$("#button_1").click(function() {
  alert("button 1 Clicked");
});

Burada, click yöntemine parametre olarak bir işlev aktarıyoruz. Ve click yöntemi, kendisine ilettiğimiz geri çağırma işlevini çağırır (veya yürütür).


1
Geri arama işlevinin kendisi daha üst düzey bir işlev değildir. Üst düzey bir işleve geçirilir.
danio

1

Geri Arama İşlevi Bağımsız değişken olarak başka bir işleve iletilen işlev.

function test_function(){       
 alert("Hello world");  
} 

setTimeout(test_function, 2000);

Not: Yukarıdaki örnekte, setTimeout işlevi için bağımsız değişken olarak test_function kullanılmıştır.


1
Stack Overflow'a hoş geldiniz! Bir soruyu cevaplamadan önce daima mevcut cevapları okuyun. Bu cevap zaten sağlandı. Cevabı tekrarlamak yerine mevcut cevabı oylayın. İyi yanıtlar yazmayla ilgili bazı yönergeleri burada bulabilirsiniz .
dferenc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.