D.ershane D Programlama Dili Dersleri

çökme: [crash], programın hata ile sonlanması
çöp toplayıcı: [garbage collector], işi biten nesneleri sonlandıran düzenek
değer türü: [value type], değer taşıyan tür
dilim: [slice], başka bir dizinin bir bölümüne erişim sağlayan yapı
eşleme tablosu: [associative array], elemanlarına tamsayı olmayan indekslerle de erişilebilen veri yapısı (bir 'hash table' gerçekleştirmesi)
nesne: [object], belirli bir sınıf veya yapı türünden olan değer
referans türü: [reference type], başka bir nesneye erişim sağlayan tür
şablon: [template], derleyicinin örneğin 'türden bağımsız programlama' için kod üretme düzeneği
... bütün sözlük

Bölümler
İngilizce Kaynaklar
Diğer



null değeri ve is işleci

Bir önceki derste referans türünden olan değişkenlerin hiçbir nesneye erişim sağlamadan da oluşturulabileceklerini söylemiştim:

    File erişimSağlayan = new File("mektup");

    File dosya;  // erişim sağlamayan

Bir referans türü olduğu için yukarıdaki dosya'nın bir kimliği vardır; ama erişim sağladığı bir işletim sistemi dosyası henüz yoktur. Böyle bir değişkenin bellekte şu şekilde durduğunu düşünebiliriz:

       dosya
   ---+-----+---
      |  o  |
   ---+--|--+---
         ▼
         ?

Not: Yukarıdaki soru işaretinin yerinde aslında null olması gerekiyor; aşağıda gösteriyorum.

Böyle bir değişken kendisine bir nesne atanana kadar kullanılamaz bir durumdadır. Doğal olarak, erişim sağladığı bir File nesnesi olmadığı için o dosya ile işlemler yapmamız beklenemez:

    File dosya;
    dosya.writefln("merhaba");

O işlem programın çökmesine neden olur:

$ ./deneme
Segmentation fault

"Segmentation fault", programın geçerli olmayan bir bellek bölgesine erişmeye çalıştığı için işletim sistemi tarafından acil olarak sonlandırıldığını gösterir.

Hatta dosya'nın başka bir değişkene eşit olup olmadığını bile denetlemek yasal değildir:

    File geçerliDosya = new File("deneme");
    File dosya;

    if (dosya == geçerliDosya) {
        // ...
    }

Program o durumda da çöker:

$ ./deneme
Segmentation fault

dosya ve geçerliDosya'nın eşitlik karşılaştırmaları, erişim sağladıkları nesneler düzeyinde yapılır; asıl nesnelerin eşit olup olmadıklarına bakılır. Geçerli bir nesnesi olmadığı için dosya ile böyle bir işlem de yapılamaz.

null değeri

Erişim sağladığı nesne henüz belli olmayan referans türü değişkenleri null özel değerine sahiptir. Bu değeri de herhangi başka bir değer gibi yazdırabiliriz:

    dout.writefln(null);

Bu değer, diğer bütün dillerde olduğu gibi, D'de de 0 özel değerini taşır. Yukarıdaki satırın çıktısı:

0000

Değeri null olan bir değişken çok kısıtlı sayıda işlemde kullanılabilir:

  1. Erişim sağlaması için geçerli bir nesne atamak
  2.     dosya = new File("muzik_listesi", FileMode.In);
    

    O atamadan sonra artık dosya'nın erişim sağladığı bir nesne vardır. Bu atamadan sonra, dosya artık bütün File işlemleri için kullanılabilir.

  3. null olup olmadığını denetlemek
  4.     if (dosya == null)     // ← derleme HATASI
    

    Ne yazık ki, == işleci asıl nesneleri karşılaştırdığı için; ve bir null değişkenin eriştirdiği geçerli bir nesne bulunmadığı için, o ifade derlenemez.

    Bu yüzden, bir değişkenin null olup olmadığını denetlemek için is işleci kullanılır.

is işleci

is, İngilizce'de "olmak" fiilinin "öyledir" kullanımındaki anlamına sahiptir. Bu dersi ilgilendiren kullanımında ikili bir işleçtir, yani sol ve sağ tarafına iki değer alır. Bu iki değer aynıysa true, değilse false üretir.

Not: is'in örneğin şablon olanağında tekli işleç olarak kullanıldığı durumlar da vardır.

İki değerden birisinin null olabildiği durumlarda == işlecinin kullanılamadığını gördük. Onun yerine is'i kullanmak gerekir. "Bu değişken null ise" koşulunu denetlemeye yarar:

    if (dosya is null) {
        // hiçbir nesneye erişim sağlamıyor
    }

is, başka türlerle de kullanılabilir. Örneğin iki tamsayı değişkenin değerleri şöyle karşılaştırılabilir:

    if (hız is yeniHız) {
        // ikisi aynı değerde
    } else {
        // ikisi farklı değerde
    }

Dilimlerde de iki dilimin aynı elemanlara erişim sağlayıp sağlamadıklarını denetler:

    if (dilim is dilim2) {
        // aynı elemanları paylaşıyorlar
    }
!is işleci

== ve != işleçlerine benzer şekilde, is'in tersi !is işlecidir. Değerler eşit olmadığında true üretir:

    if (hız !is yeniHız) {
        // farklı değerlere sahipler
    }
null değer atamak

Referans türlerinin kendi değerleri olmadığını ve başka bir değere erişim sağladıklarını biliyoruz. Böyle bir değişkene null değerini atamak, o değişkenin artık hiçbir değere erişim sağlamamasına neden olur.

Eğer bu atama sonucunda asıl değere erişen başka referans değişkeni kalmamışsa, asıl değer çöp toplayıcı tarafından sonlandırılacaktır. Hiçbir referans tarafından erişilmiyor olması, o değerin artık kullanılmadığını gösterir.

Örnek olarak, önceki dersteki iki değişkenin tek bir değere eriştiği duruma bakalım:

    auto dosya = new File("oyuncu_listesi", FileMode.Out);
    auto dosya2 = dosya;
    (isimsiz File nesnesi)       dosya        dosya2
 ---+-------------------+---  ---+---+---  ---+---+---
    |        ...        |        | o |        | o |
 ---+-------------------+---  ---+-|-+---  ---+-|-+--
              ▲                    |            |
              |                    |            |
              +--------------------+------------+

Bu değişkenlerden birisine null atamak, onun bu değerle ilişkisini keser:

    dosya = null;

File nesnesine artık yalnızca dosya2 tarafından erişilmektedir:

    (isimsiz File nesnesi)       dosya        dosya2
 ---+-------------------+---  ---+---+---  ---+---+---
    |        ...        |        | o |        | o |
 ---+-------------------+---  ---+-|-+---  ---+-|-+--
              ▲                    ▼            |
              |                   null          |
              |                                 |
              +---------------------------------+

İsimsiz File nesnesine erişen son referans olan dosya2'ye de null atanması, asıl nesnenin sonlanmasına neden olur:

    dosya2 = null;

Çöp toplayıcı asıl nesneyi türüne göre ya hemen, ya da ilerideki bir zamanda sonlandıracaktır. Program açısından artık o nesne yoktur çünkü o nesneye erişen referans kalmamıştır:

                                 dosya        dosya2
 ---+-------------------+---  ---+---+---  ---+---+---
    |                   |        | o |        | o |
 ---+-------------------+---  ---+-|-+---  ---+-|-+--
                                   ▼            ▼
                                  null         null

Eşleme tabloları dersinin birinci problemi, bir eşleme tablosunu boşaltan üç yöntem gösteriyordu. Şimdi o yöntemlere bir dördüncüsünü ekleyebiliriz; eşleme tablosu değişkenine null değer atamak, değişkenin erişim sağladığı asıl tablo ile ilişkisini keser:

    string[int] isimleSayılar;
    // ...
    isimleSayılar = null;     // artık hiçbir elemana erişim
                              // sağlamaz

Yukarıdaki File örneğine benzer şekilde, eğer isimleSayılar asıl tabloya erişim sağlayan son referans idiyse, asıl tablonun elemanları çöp toplayıcı tarafından sonlandırılacaklardır.

Bir dilimin de artık hiçbir elemana erişim sağlaması istenmiyorsa null atanabilir:

    int[] dilim = dizi[ 10 .. 20 ];
    // ...
    dilim = null;     // artık hiçbir elemana erişim sağlamaz
Özet