Groovy - Kapanışlar

Kapatma, kısa ve anonim bir kod bloğudur. Normalde birkaç satırlık bir kodu kapsar. Bir yöntem, kod bloğunu bir parametre olarak bile alabilir. Doğası gereği anonimdirler.

Aşağıda basit bir kapanış örneği ve neye benzediğini görebilirsiniz.

class Example {
   static void main(String[] args) {
      def clos = {println "Hello World"};
      clos.call();
   } 
}

Yukarıdaki örnekte, kod satırı - {println "Merhaba Dünya"} kapanış olarak bilinir. Bu tanımlayıcı tarafından referans verilen kod bloğu, call deyimi ile yürütülebilir.

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

Hello World

Kapanışlarda biçimsel parametreler

Kapanışlar ayrıca onları Groovy'deki yöntemler gibi daha kullanışlı hale getirmek için biçimsel parametreler içerebilir.

class Example {
   static void main(String[] args) {
      def clos = {param->println "Hello ${param}"};
      clos.call("World");
   } 
}

Yukarıdaki kod örneğinde, kapamanın bir parametre almasına neden olan $ {param} kullanımına dikkat edin. Clos.call deyimi aracılığıyla closure çağrısı yaparken, artık closure'a bir parametre geçirme seçeneğimiz var.

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

Hello World

Bir sonraki çizim önceki örneği tekrarlar ve aynı sonucu verir, ancak kullanılabileceği gibi atıfta bulunulan örtük tek bir parametrenin olduğunu gösterir. Burada 'it' Groovy'de bir anahtar kelimedir.

class Example {
   static void main(String[] args) {
      def clos = {println "Hello ${it}"};
      clos.call("World");
   } 
}

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

Hello World

Kapanışlar ve Değişkenler

Daha resmi olarak, kapanışlar, kapanış tanımlandığı anda değişkenlere atıfta bulunabilir. Aşağıda bunun nasıl başarılabileceğine dair bir örnek verilmiştir.

class Example {     
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = {param -> println "${str1} ${param}"}
      clos.call("World");
		
      // We are now changing the value of the String str1 which is referenced in the closure
      str1 = "Welcome";
      clos.call("World");
   } 
}

Yukarıdaki örnekte, kapanışa bir parametre aktarmanın yanı sıra, str1 adında bir değişken de tanımlıyoruz. Kapanış ayrıca değişkeni parametre ile birlikte alır.

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

Hello World 
Welcome World

Yöntemlerde Kapatmaları Kullanma

Kapanışlar ayrıca yöntemlerin parametreleri olarak da kullanılabilir. Groovy'de, Listeler ve koleksiyonlar gibi veri türleri için yerleşik yöntemlerin çoğu, parametre türü olarak kapanışlara sahiptir.

Aşağıdaki örnek, bir kapatmanın bir yönteme parametre olarak nasıl gönderilebileceğini gösterir.

class Example { 
   def static Display(clo) {
      // This time the $param parameter gets replaced by the string "Inner"         
      clo.call("Inner");
   } 
	
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = { param -> println "${str1} ${param}" }
      clos.call("World");
		
      // We are now changing the value of the String str1 which is referenced in the closure
      str1 = "Welcome";
      clos.call("World");
		
      // Passing our closure to a method
      Example.Display(clos);
   } 
}

Yukarıdaki örnekte,

  • Bir kapanışı argüman olarak alan Display adında statik bir yöntem tanımlıyoruz.

  • Daha sonra ana yöntemimizde bir kapanış tanımlıyor ve bunu parametre olarak Display yöntemimize geçiriyoruz.

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

Hello World 
Welcome World 
Welcome Inner

Koleksiyonlarda ve Dizede Kapanışlar

Birkaç List, Map ve String yöntemi, bir kapanışı bağımsız değişken olarak kabul eder. Bu veri türlerinde kapanışların nasıl kullanılabileceğine dair bir örneğe bakalım.

Kapanışları Listelerle Kullanma

Aşağıdaki örnek, Closure'ların Listelerle nasıl kullanılabileceğini gösterir. Aşağıdaki örnekte önce basit bir değerler listesi tanımlıyoruz. Liste toplama türü daha sonra adı verilen bir işlevi tanımlar.each. Bu işlev bir parametre olarak bir kapanışı alır ve kapanışı listenin her bir öğesine uygular.

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      lst.each {println it}
   } 
}

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

11 
12 
13 
14

Kapatmaları Haritalar ile Kullanma

Aşağıdaki örnek, kapanışların Haritalar ile nasıl kullanılabileceğini gösterir. Aşağıdaki örnekte ilk önce basit bir anahtar değer öğeleri Haritası tanımlıyoruz. Harita koleksiyonu türü daha sonra .each adlı bir işlevi tanımlar. Bu işlev, bir kapanışı parametre olarak alır ve kapanışı haritanın her bir anahtar / değer çiftine uygular.

class Example {
   static void main(String[] args) {
      def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]             
      mp.each {println it}
      mp.each {println "${it.key} maps to: ${it.value}"}
   } 
}

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

TopicName = Maps 
TopicDescription = Methods in Maps 
TopicName maps to: Maps 
TopicDescription maps to: Methods in Maps

Genellikle, bir koleksiyonun üyeleri arasında yineleme yapmak ve yalnızca öğe bazı kriterleri karşıladığında bazı mantıkları uygulamak isteyebiliriz. Bu, kapanışta bir koşullu ifade ile kolayca ele alınır.

class Example {
   static void main(String[] args) {
      def lst = [1,2,3,4];
      lst.each {println it}
      println("The list will only display those numbers which are divisible by 2")
      lst.each{num -> if(num % 2 == 0) println num}
   } 
}

Yukarıdaki örnek, listedeki her bir öğenin 2'ye bölünebilir olup olmadığını kontrol etmek için kullanılan kapanışta kullanılan koşullu if (num% 2 == 0) ifadesini gösterir.

Yukarıdaki programı çalıştırdığımızda şu sonucu alacağız -

1 
2 
3 
4 
The list will only display those numbers which are divisible by 2.
2 
4

Closures ile kullanılan yöntemler

Kapakların kendileri bazı yöntemler sağlar.

Sr.No. Yöntemler ve Açıklama
1 bul ()

Find yöntemi, bir koleksiyondaki bazı ölçütlerle eşleşen ilk değeri bulur.

2 hepsini bul()

Kapanma koşulu ile eşleşen alıcı nesnedeki tüm değerleri bulur.

3 herhangi () ve her ()

Yöntem, bir Boolean yükleminin en az bir öğe için geçerli olup olmadığını kontrol eden bir koleksiyonun her bir öğesi aracılığıyla yinelenir.

4 toplamak()

Toplama yöntemi, bir koleksiyon aracılığıyla yinelenir, her öğeyi transformatör olarak kapanışı kullanarak yeni bir değere dönüştürür.