const ve immutable Kavramları
Çeviren: Ali Çehreli
Tarih: 13 Temmuz 2009
İngilizcesi: Const and Immutable
[Çevirenin notu: "constant" ve "immutable" sözcüklerinin hem İngilizce hem Türkçe karşılıkları temelde aynıdır: sabit, değişmez. Türkçe'de const başka programlama dillerinde zaten "sabit" olarak geçtiği için ben burada da aynı karşılığı kullanıyorum. Böylece immutable'a "değişmez" kalıyor.]
Bir veri yapısını veya bir arayüz fonksiyonunu incelerken hangi verilerin değişmeyeceklerini, hangilerinin değişebileceklerini, ve değişimlerin kimin tarafından yapılabileceğini bilmek çok önemlidir. Bunu sağlayan düzeneklerden birisi, dilin tür sistemidir. D'de her veri const veya immutable olarak belirtilebilir. Özellikle belirtilmemişse veri değişebilir demektir.
immutable, verinin değişemez olduğunu bildirir. Bu tür veriler, ilk değerlerini aldıktan programın sonuna kadar aynı değerde kalırlar. Bunlar ROM'a veya donanımın değiştirilemez olarak işaretlediği bellek bölgelerine yerleştirilmiş olabilirler. Verinin değişemez olduğunun baştan biliniyor olması; derleyici için eniyileme olanaklarının artmasının yanında, fonksiyonel programlama açısından da yararlıdır.
const, verinin const olarak belirlenen referans yoluyla değiştirilemeyeceğini bildirir. Aynı veri, başka bir referans aracılığıyla değiştirilebilir durumda olabilir. const, fonksiyonların verileri değiştirmeyecekleri sözü vermeleri için kullanılır.
const ve immutable geçişlidirler; onlar aracılığıyla erişilen başka veriler de yine const veya immutable'dırlar.
immutable depolama türü
immutable'ın en basit kullanımı sabit değerler oluşturmaktır.
immutable int x = 3; // x 3'tür x = 4; // hata: x değiştirilemez char[x] s; // s, uzunluğu 3 olan bir char dizisidir
Verinin türü, ilkleme için kullanılan değerden çıkarsanabilir:
immutable y = 4; // y'nin türü int'tir y = 5; // hata: y değiştirilemez
Eğer ilkleme değeri henüz mevcut değilse, değişmez veri daha sonraki bir noktada kendisiyle ilgili kurucuda ilklenebilir.
immutable int z; void deneme() { z = 3; // hata: z değiştirilemez } static this() { z = 3; // olur: ilkleme değeri z'nin tanımlandığı // noktada bilinmiyorsa burada ilklenir }
Yerel olmayan bir immutable verinin ilk değerinin derleme zamanında hesaplanabilen bir türden olması gerekir.
int foo(int f) { return f * 3; } int i = 5; immutable x = 3 * 4; // olur: 12 immutable y = i + 1; // hata: derleme zamanında işletilmez immutable z = foo(2) + 1; // olur: foo(2) derleme zamanında 7 // olarak hesaplanır
static olmayan yerel immutable veriler çalışma zamanında ilklenirler.
int foo(int f) { immutable x = f + 1; // çalışma zamanında işletilir x = 3; // hata: x değiştirilemez }
Değişmezlik geçişli olduğu için immutable yoluyla erişilen veri de değişmezdir.
immutable char[] s = "foo"; s[0] = 'a'; // hata: s bir immutable veri referansıdır s = "bar"; // hata: s değiştirilemez
immutable veriler soldeğerlerdir [lvalue]. Yani adresleri alınabilir ve bellekte yer tutarlar.
const depolama türü
const bildirimi ile immutable bildirimi arasında şunlardan başka fark yoktur:
- Veri,
constolarak bildirilmiş referansı yoluyla değiştirilemez, ama aynı vericonstolmayan başka bir referans yoluyla değiştirilebilir. constbildiriminin kendi türü deconst'tır.
immutable türler
Değeri değişmeyecek olan verilerin türleri immutable olarak bildirilebilir. immutable anahtar sözcüğü bir tür kurucusu olarak düşünülebilir:
immutable(char)[] s = "merhaba";
immutable anahtar sözcüğü, o kullanımda parantez içindeki türü etkiler. Orada s'ye yeni değerler atanabiliyor olsa da, s'nin içindeki değerler değiştirilemez:
s[0] = 'b'; // hata: s[] değiştirilemez s = null; // olur: s'nin kendisi immutable değil
immutable geçişlidir; kendisi yoluyla erişilen veri de değiştirilemez:
immutable(char*)** p = ...; p = ...; // olur: p immutable değil *p = ...; // olur: *p immutable değil **p = ...; // hata: **p değiştirilemez ***p = ...; // hata: ***p değiştirilemez
Depolama türü olarak kullanılan immutable, bütün bildirimin türü için kullanılan tür kurucusu immutable'ın eşdeğeridir:
immutable int x = 3; // x'in türü immutable(int) olur immutable(int) y = 3; // y değiştirilemez
Değiştirilemeyen veri oluşturmak
Bunun bir yolu, değiştirilemeyen değerler kullanmaktır. Örneğin dizgi sabitleri değiştirilemezler:
auto s = "merhaba"; // s'nin türü immutable(char)[] olur char[] p = "dünya"; // hata: immutable, değiştirilebilen bir // türe otomatik olarak dönüşemez
Diğer yol, tür değişiminde immutable kullanmaktır. Ama böyle yapıldığında, veriyi değiştirebilecek başka referansların bulunmadığını sağlamak programcının sorumluluğundadır.
char[] s = ...; immutable(char)[] p = cast(immutable)s; // tanımsız davranış immutable(char)[] p = cast(immutable)s.dup; // olur: p, .dup ile kopyalanan yeni kopyanın tek referansıdır
Dizilerin immutable kopyalarını almanın kolay yolu, .idup dizi niteliğini kullanmaktır:
auto p = s.idup; p[0] = ...; // hata: p[] değiştirilemez
immutable'ın tür değişimi ile kaldırılması
Değişmezlik tür dönüşümü ile kaldırılabilir:
immutable int* p = ...; int* q = cast(int*)p;
Ama bu, verinin artık değiştirilebileceği anlamına gelmez:
*q = 3; // derleyici izin verir ama tanımsız davranıştır
Bazı durumlarda immutable'ın kaldırılabilmesi gerekebilir. Örneğin kaynak kodlarına sahip olmadığımız bir kütüphane, immutable olması gereken fonksiyon parametrelerini immutable olarak bildirmemiş olabilir. O kütüphane fonksiyonlarını çağırabilmek için immutable'ı tür dönüşümü yoluyla kaldırmak zorunda kalırız; ancak bu durumda sorumluluk tamamen programcıya aittir; derleyici o veri için artık denetim sağlayamaz.
immutable üye fonksiyonlar
Üye fonksiyonları immutable olarak bildirmek, o nesnenin o üye fonksiyon içindeyken değiştirilemeyeceği anlamına gelir. Bu, nesne içinde tanımlı bütün verileri ve onların this yoluyla erişildiği durumları kapsar:
struct S { int x; immutable void foo() { x = 4; // hata: x değiştirilemez this.x = 4; // hata: x değiştirilemez } }
const ve immutable belirteçleri üye fonksiyonların parametre listesinden sonra da yazılabilirler:
struct S { void bar() immutable { } }
const türler
const türler de immutable türler gibidirler; ama bu türden olan veriler const olmayan referanslar yoluyla değiştirilebilirler.
const üye fonksiyonlar
const üye fonksiyonlar içindeyken nesnenin this yoluyla erişilen üyeleri değiştirilemez.
Otomatik dönüşümler
Değişken (normal) türler ve immutable türler otomatik olarak const'a dönüşürler. Değişken türler immutable türlere, immutable türler de değişken türlere otomatik olarak dönüşmezler.
D'deki const ve immutable'ın C++'daki const ile karşılaştırılması
| Olanak | D | C++98 |
|---|---|---|
| const anahtar sözcüğü | var | var |
| immutable anahtar sözcüğü | var | yok |
| const yazımı | Fonksiyon bildirimi gibi:
// const int // const işaretçisi // işaretçisi: const(int*)* p; |
Sonda:
// const int // const işaretçisi // işaretçisi: const int *const *p; |
| const geçişliliği | var:
// const int // const işaretçisi // const işaretçisi: const int** p; **p = 3; // hata |
yok:
// int // işaretçisi // const işaretçisi: int** const p; **p = 3; // olur |
| const'ı kaldırmak | var:
// const int işaretçisi: const(int)* p; int* q = cast(int*)p; //olur |
var:
// const int işaretçisi:
const int* p;
int* q = const_cast<int*>p;
// olur
|
| const'ı kaldırdıktan sonra değişiklik | yok:
// const int işaretçisi: const(int)* p; int* q = cast(int*)p; *q = 3; // tanımsız davranış |
var:
// const int işaretçisi: const int* p; int* q = const_cast<int*>p; *q = 3; // olur |
| fonksiyon yüklemede üst düzey const'ın etkisi | var:
void foo(int x); void foo(const int x);//olur |
yok:
void foo(int x); void foo(const int x);//hata |
| aynı const'a değişken olarak da erişebilmek | var:
void foo(const int* x, int* y) { bar(*x); // bar(3) *y = 4; bar(*x); // bar(4) } ... int i = 3; foo(&i, &i); |
var:
void foo(const int* x,
int* y)
{
bar(*x); // bar(3)
*y = 4;
bar(*x); // bar(4)
}
...
int i = 3;
foo(&i, &i);
|
| aynı immutable'a değişken olarak da erişebilmek | yok:
void foo(immutable int* x, int* y) { bar(*x);// bar(3) *y = 4; // tanımsız // davranış bar(*x);// bar(??) } ... int i = 3; foo(cast(immutable)&i, &i); |
immutable desteklenmez |
| dizgi sabitlerinin türü |
immutable(char)[] |
const char[N] |
| dizgi sabitinin değişken dizgiye otomatik dönüşümü | izin verilmez | izin verilir ama emekliye ayrılmış [deprecated] bir olanaktır |

Kitaplar
Tanıtım
İletişim
Hakları