Desenler (Patterns)

Desenler, Dart dilinde ifadeler ve deyimler gibi bir sözdizimi kategorisidir. Bir desen, gerçek değerlere karşı eşleştirilebilecek bir değer kümesinin şeklini temsil eder.

Bu sayfa şunları içerir:

  1. Desenlerin ne işe yaradığı.

  2. Dart kodunda desenlerin nerede kullanılabileceği.

  3. Desenlerin yaygın kullanım durumları.

Desen türleri sayfasını inceleyerek farklı desen türleri hakkında bilgi edinebilirsiniz.

Desenler Ne Yapar?

Desenlerin İşlevi Genel olarak, bir desen, bir değeri eşleştirebilir, bir değeri parçalayabilir veya her ikisini de yapabilir, bağlam ve desenin şekline bağlı olarak.

İlk olarak, desen eşleştirmesi, bir verinin belirli bir şekle sahip olup olmadığını kontrol etmenizi sağlar:

  • Belirli bir şekle sahipse.

  • Belirli bir sabite eşitse.

  • Başka bir şeye eşitse.

  • Belirli bir türe sahipse. Daha sonra, desen parçalaması, bir değeri bileşen parçalarına ayırmak için uygun bir deklaratif sözdizimi sağlar. Aynı desen, bu süreçte bazı veya tüm bileşenlere yeni değişkenler bağlamana da izin verebilir.

Eşleşme

Bir desen her zaman bir değeri test eder ve değerin beklediğiniz şekle sahip olup olmadığını belirler. Başka bir deyişle, değerin deseni eşleşip eşleşmediğini kontrol ediyorsunuz.

Eşleşenin ne oluşturduğu, hangi türde bir desen kullandığınıza bağlıdır. Örneğin, bir sabit deseni, değerin desenin sabitine eşit olup olmadığını kontrol eder:

switch (number) {
  // Sabit deseni, 1 == number ise eşleşir.
  case 1:
    print('bir');
}

Birçok desen, bazen dış ve iç desenler olarak adlandırılan alt desenleri kullanır. Desenler, alt desenlerinde özyineli (rekürsif) olarak eşleşir. Örneğin, herhangi bir koleksiyon tipi deseninin bireysel alanları değişken desenler veya sabit desenler olabilir:

const a = 'a';
const b = 'b';
switch (obj) {
  // Liste deseni [a, b], obj ilk olarak bir liste ise eşleşir
  // ardından alanları 'a' ve 'b' sabit desenlerle eşleşirse.
  case [a, b]:
    print('$a, $b');
}

Eşleşen bir değerin bazı bölümlerini görmezden gelmek için bir joker deseni kullanabilirsiniz. Liste desenleri durumunda bir dinlenme öğesi kullanabilirsiniz.

Parçalama

Bir nesne ve desen eşleştiğinde, desen ardından nesnenin verilerine erişebilir ve bunları parçalayabilir. Başka bir deyişle, desen nesneyi parçalar:

var numList = [1, 2, 3];
// Liste deseni [a, b, c], numList'ten üç elemanı parçalar...
var [a, b, c] = numList;
// ...ve bunları yeni değişkenlere atar.
print(a + b + c);

Herhangi bir türdeki deseni bir parçalama desenine iç içe yerleştirebilirsiniz. Örneğin, bu durum deseni, ilk öğesi 'a' veya 'b' olan iki öğeli bir listeyi eşleşip parçalar:

switch (list) {
  case ['a' || 'b', var c]:
    print(c);
}

Desenlerin Kullanıldığı Yerler

Desenleri Dart dilinde birkaç yerde kullanabilirsiniz:

  1. Yerel değişken bildirimleri ve atamaları

  2. for ve for-in döngüleri

  3. if-case ve switch-case

  4. Toplama literallerinde kontrol akışı Bu bölüm, desenlerle eşleştirme ve parçalama için ortak kullanım durumlarını açıklar.

Değişken Bildirimi

Deseni, Dart'ın yerel değişken bildirimi izin verdiği herhangi bir yerde kullanabilirsiniz. Desen, bildirimin sağında bulunan değere karşı eşleşir. Eşleştiğinde değeri parçalar ve yeni yerel değişkenlere bağlar:

// Yeni değişkenler a, b ve c'yi bildirir.
var (a, [b, c]) = ('str', [1, 2]);

Desen değişken bildirimi, var veya final ile başlamalıdır ve bir desenle devam etmelidir.

Değişken Atama

Değişken atama deseni, atama operatörünün sol tarafına düşer. İlk olarak eşleştirilen nesneyi parçalar. Ardından değerleri mevcut değişkenlere atar, yeni bir değişken oluşturmak yerine:

İki değişkenin değerlerini üçüncü geçici bir değişken oluşturmadan değiştirmek için değişken atama deseni kullanın:

var (a, b) = ('sol', 'sağ');
(b, a) = (a, b); // Değerleri değiştir.
print('$a $b'); // "sağ sol" yazdırır.

Switch Deyimleri ve İfadeleri

Her case ifadesi bir deseni içerir. Bu, switch ifadeleri ve deyimleri, aynı zamanda if-case ifadeleri için de geçerlidir. Bir case için herhangi bir deseni kullanabilirsiniz.

Case desenleri reddedilebilir. Bunlar, anahtar üzerinde eşleşen nesneyi parçalayabilir ve değişmezse devam edebilir. Bir desenin case içinde parçaladığı değerler, yalnızca o case'in gövde kısmı içinde geçerlidir.

switch (obj) {
  // 1 == obj durumunda eşleşirse.
  case 1:
    print('bir');

  // obj değeri 'ilk' ve 'son' sabit değerleri arasında ise eşleşir.
  case >= ilk && <= son:
    print('aralıkta');

  // obj, iki alanı olan bir kayıt ise,
  // 'a' ve 'b' alanlarını 'a' ve 'b' değişkenlerine atar.
  case (var a, var b):
    print('a = $a, b = $b');

  default:
}

Switch ifadelerinde veya deyimlerinde birden çok case'in aynı gövdeyi paylaşmasını sağlamak için kullanışlıdır:

var birincilMi = switch (renk) {
  Renkler.kirmizi || Color.sari || Color.mavi => true,
  _ => false
};

Switch ifadelerinde birden çok case aynı gövdeyi paylaşabilir, ancak mantık-veya desenleri kullanmadan da yapılabilir, ancak mantık-veya desenleri, birden çok case'in bir koruma paylaşmasına izin vermek için hala benzersiz bir şekilde kullanışlıdır:

switch (sekil) {
  case Kare(boyut: var b) || Yuvarlak(boyut: var b) when b > 0:
    print('Boş olmayan simetrik şekil');
}

Koruma ifadeleri, bir case'in bir parçası olarak herhangi bir koşulu değerlendirir ve koşul yanlışsa switch'ten çıkmaz (bir if ifadesinde kullanmak, koşul yanlışsa ifadenin gövdesini atlamak gibi).

switch (eslemek) {
  case (int a, int b):
    if (a > b) print('İlk öğe daha büyük');
  // Eğer yanlışsa hiçbir şey yazdırmaz ve switch'ten çıkar.
  case (int a, int b) when a > b:
    // Eğer yanlışsa hiçbir şey yazdırmaz, ancak bir sonraki case'e geçer.
    print('İlk öğe daha büyük');
  case (int a, int b):
    print('İlk öğe daha büyük değil');
}

For ve For-in Döngüleri

For ve for-in döngülerinde desenleri kullanarak bir koleksiyon içinde dolaşabilir ve değerleri parçalayabilirsiniz.

Bu örnek, bir <Map>.entries çağrısının döndürdüğü MapEntry nesnelerini parçalamak için for-in döngüsünde nesne parçalama kullanır:

Map<String, int> gecmis = {
  'a': 23,
  'b': 100,
};

for (var MapEntry(key: key, value: sayi) in gecmis.entries) {
  print('$key, $sayi kez meydana geldi');
}

Nesne deseni, gecmis.entries'in adlandırılmış türüne sahip olduğunu kontrol eder ve ardından adlandırılmış alan desenleri key ve value içine girer. Her tekrarda MapEntry üzerinde key ve value getter'ları çağırır ve sonuçları sırasıyla key ve sayi adlı yerel değişkenlere bağlar.

Getter çağrısının sonucunu aynı ada sahip bir değişkene bağlamak yaygın bir kullanım durumudur, bu nedenle nesne desenleri, değişken deseninden key: key gibi gereksiz bilgileri çıkarmak için de getter adını çıkarabilir. Bu, değişken desenini key: key yerine :key olarak basitleştirmenizi sağlar:

for (var MapEntry(:key, value: sayi) in gecmis.entries) {
  print('$key, $sayi kez meydana geldi');
}

Desenlerin Kullanım Durumları

Önceki bölüm, desenlerin diğer Dart kod yapılarına nasıl uyduğunu açıklar. İki değişkenin değerlerini değiştirmek veya bir harita içindeki anahtar-değer çiftlerini parçalamak gibi ilginç kullanım durumlarına örnekler gördünüz. Bu bölüm, desenleri neden ve ne zaman kullanmak isteyebileceğinizi, hangi problemleri çözdüğünü ve hangi deyimleri en iyi şekilde tamamladığınıınızı açıklar.

Çoklu Dönüşleri Parçalama

Kayıtlar, tek bir işlev çağrısından birden çok değeri bir araya getirme ve döndürme yeteneği sunar. Desenler, bu işlevin değerlerini doğrudan bir işlev çağrısının içindeki yerel değişkenlere parçalama yeteneği ekler.

Tek tek her bir kayıt alanı için yeni yerel değişkenler bildirmek yerine, bir işlevin döndürdüğü bir kaydın alanlarını yerel değişkenlere bağlamak için desen bildirimi veya atama deseni kullanabilirsiniz:

var bilgi = kisiBilgi(json);
var isim = bilgi.$1;
var yas = bilgi.$2;

Bir işlevin döndürdüğü bir kaydın alanlarını, bir değişken bildirimi veya atama deseni ve bir kayıt deseni kullanarak yerel değişkenlere bağlamak için:

var (isim, yas) = kisiBilgi(json);

Sınıf Örneklerini Parçalama

Nesne desenleri, adlandırılmış nesne türleriyle eşleşir ve nesnenin sınıfının zaten açıkladığı getter'ları kullanarak verilerini parçalamanıza olanak tanır.

Bir sınıf örneğini parçalamak için, adlandırılmış türü ve parçalanacak özellikleri parantez içinde kullanabilirsiniz:

final Ogrenci benimOgrencim = Ogrenci(ad: 'Bulut', yas: 16);
var Ogrenci(isim, yas) = benimOgrencim;
print('İsim: $isim, Yaşı: $yas');

Cebirsel Veri Tipleri

Nesne parçalama ve switch case ifadeleri, cebirsel bir veri tipi tarzında kod yazmaya olanak tanır. Bu yöntemi kullanmanız gereken durumlar şunlardır:

  • İlgili türler ailesine sahipsiniz.

  • Her bir tür için belirli davranışlara ihtiyaç duyan bir işleminiz var.

  • Bu davranışı tüm farklı tür tanımlarına yaymak yerine, bu davranışı bir yerde gruplamak istiyorsunuz.

Her tür için işlemi her seferinde bir örnek yöntemi olarak uygulamak yerine, işlemin farklı varyasyonlarını tek bir fonksiyonda tutun ve bu fonksiyon içinde tür alt tiplerine geçiş yapın:

import 'dart:math' as math;

sealed class Sekil {}

class Kare implements Sekil {
  final double kenarUzunlugu;
  Kare(this.kenarUzunlugu);
}

class Daire implements Sekil {
  final double yariCap;
  Daire(this.yariCap);
}

double alanHesapla(Sekil sekil) => switch (sekil) {
  Kare(kenarUzunlugu: var k) => k * k,
  Daire(yariCap: var r) => math.pi * r * r
};

Gelen JSON Verisinin Doğrulanması

Harita ve liste desenleri, JSON verilerindeki anahtar-değer çiftlerini parçalamak için oldukça kullanışlıdır:

var json = {
  'user': ['Bayram', 24]
};
var {'user': [isim, yas]} = json;

Ancak genellikle veri dış bir kaynaktan, örneğin bir ağ üzerinden gelir. Bu durumda, veriyi önce doğrulamanız gerekir.

Desenler olmadan doğrulama çok uzun olabilir:

if (json is Map<String, Object?> &&
    json.length == 1 &&
    json.containsKey('kullanici')) {
  var kullanici = json['kullanici'];
  if (kullanici is List<Object> &&
      kullanici.length == 2 &&
      kullanici[0] is String &&
      kullanici[1] is int) {
    var isim = kullanici[0] as String;
    var yas = kullanici[1] as int;
    print('Kullanıcı $isim $yas yaşında.');
  }
}

Tek bir durum deseni aynı doğrulamayı sağlayabilir. Tek durumlar genellikle if-case ifadeleri olarak en iyi çalışır. Desenler, JSON'u doğrulamanın daha deklaratif ve çok daha az uzun bir yolunu sağlar:

if (json case {'kullanici': [String isim, int yas]}) {
  print('Kullanıcı $isim $yas yaşında.');
}

Bu durum deseni aynı anda şunları doğrular:

  • json bir Maps, çünkü devam edebilmek için önce dış harita deseniyle eşleşmelidir.

    • Ve, çünkü bir harita ise, aynı zamanda json'ın null olmadığını da onaylar.

  • json bir kullanici anahtarını içerir.

  • kullanici anahtarı iki değeri içeren bir liste ile eşleşir.

  • Liste değerlerinin türleri String ve int'tir.

  • Yeni yerel değişkenleri saklamak için isim ve yas.

Last updated