"const ref Parametreler ve const Üye İşlevler" dersinde (http://ddili.org/ders/d/const_uye_islevler.html) "const üye işlevler" başlığı altında nesneyi değiştirmeyen üye işlevlerin 'const' işaretlerinin parametre listesinden sonra yazılmasını önermiştim:
class BirSınıf
{
BirTür üyeİşlev() const
{
// ... nesneyi değiştirmeyeceği sözünü vermiş olur ...
}
}
Sağ tarafa yazılmasını önermemin bir nedeni, C++'da da öyle yazılması gerektiğiydi. D'de ise aslında o 'const' baş tarafa da yazılabilir (hatta aslında sağa da yazılabilmesini C++'daki kullanıma benzesin diyedir diye düşünebiliriz):
const BirTür üyeİşlev()
{
// ... nesneyi değiştirmeme sözü vermiş olur ...
}
O da olur ama bir sakıncası vardır: Öyle yazınca 'const'ın BirTür'e mi yoksa üye işleve mi uygulanacağı bir bakışta anlaşılmayabilir. Çünkü başka bağlamlarda 'const BirTür' gördüğümüzde o 'const'ın BirTür ile ilgili olduğunu düşünebiliriz:
const BirTür değer = // ...
Ama dikkat ederseniz bu kullanımda bile 'const' aslında 'değer' ile ilgilidir, BirTür ile değil.
Aşağıdaki biraz uzunca bir örnek oldu ama 'const' kullanımını Motor içeren bir Araba ile göstermek istiyorum. Elimizde bir Motor olsun:
import std.stdio;
import std.string;
class Motor
{
double güç_;
this(double güç)
{
güç_ = güç;
}
void güçAzalt(double miktar)
{
güç_ -= miktar;
if (güç_ < 0) {
güç_ = 0;
}
}
override string toString()
{
return format("%s", güç_);
}
}
Çok basit bir sınıf: belirli bir güçle başlıyor ve zamanla gücü azaltılabiliyor. Motor içeren bir de Araba sınıfı olsun:
class Araba
{
string marka_;
string model_;
Motor motor_;
this(string marka, string model, double güç)
{
marka_ = marka;
model_ = model;
motor_ = new Motor(güç);
}
Motor motor()
{
return motor_;
}
override string toString()
{
return format("%s %s %shp", marka_, model_, motor_);
}
}
O da çok basit bir sınıf; doğrudan motor_ üyesine erişim de sağlıyor. Sınıflar referans türleri olduklarından, Araba'nın kullanıcıları motor_ üyesinde değişiklik yapabilirler:
void main()
{
auto araba = new Araba("Mannayako", "300i", 300);
auto motor = araba.motor(); // bu motor, içerilen motor_'a erişim sağlar
motor.güçAzalt(1);
writeln(araba);
}
araba'nın içindeki motor_'un gücü azaltılır; artık 299 beygir gücündedir:
'Mannayako 300i 299hp'
Eğer amacımız kullanıcıların motora erişebilmeleri, ama onu değiştirememeleri ise, o zaman dönüş referansının const olduğunu şöyle belirtebiliriz:
class Araba
{
// ...
const(Motor) motor()
{
return motor_;
}
// ...
auto motor = araba.motor(); // şimdi const(Motor)'dur, ve o yüzden
motor.güçAzalt(1); // <-- DERLEME HATASI
Sarma (kapsülleme) gereği olarak zaten üyelere çoğu durumda 'const' erişim sağlamak istenir. Güzel...
Araba.motor işlevi ile ilgili bir 'const' konusu daha var: Araba.motor, üzerinde çağrıldığında araba nesnesinde değişiklik yapmayacağı sözü vermemektedir. O yüzden örneğin işlevin içinde 'model_ = "Cannavaro"' gibi bir değişiklik de yapıyor olabilir.
Sonuçta Araba.motor, derleyicinin gözünde nesneyi her an değiştirebilecek olan tehlikeli :) bir işlevdir. O yüzden, elimizde değiştirilemeyen bir Araba bulunduğunda onun motoruna erişemeyiz:
void foo(const(Araba) araba) // <-- Araba'ya 'const' referans
{
auto motor = araba.motor(); // <-- DERLEME HATASI
}
Araba.motor işlevinin kendisi 'const' olmadığından, derleyici araba'da değişiklik yapmayacağımız sözü bulunmadığı için elimizdeki const araba değişmesin diye derleme hatası verir.
Bu kullanımı sağlayabilmek için Araba.motor'un kendisini de const olarak işaretlememiz gerekir:
class Araba
{
// ...
const(Motor) motor() const // şimdi en sağda bir const daha var
{
return motor_;
}
// ...
}
void foo(const(Araba) araba)
{
auto motor = araba.motor(); // şimdi derlenir
}
Başta hatırlattığım derste ve yukarıda yaptığım gibi, işlevin kendisinin 'const'lığı sağ tarafa yazılabilir. Böylece o işlevin nesneyi değiştirmediği söylenmiş olur.
Aynı anlama gelen 'const', aslında işlevin tanımından önce de yazılabilir:
const const(Motor) motor() // şimdi en solda
{
return motor_;
}
Anlamı: const(Motor) döndürür ve üzerinde çağrıldığı Araba nesnesinde değişiklik yapmaz.
İki tane const yan yana gelince garip görünüyor ama başkalarının yazdıkları kodlarda karşılaşınca garipsememeliyiz.
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]
Permalink
Reply