July 19, 2009

Not: Ben interface'i kalıtım konusunda "arayüz" diye kullanmayı seviyorum. "arabirim"i de "kullanıcı arabirimi" gibi programın dış yüzeyiyle ilgili olarak algılıyorum.

Nesne yönelimli programlamada doğru kalıtımın büyük bir çoğunluğu arayüz kalıtımıdır. Örneğin Şekil sınıfının çiz() diye bir üyesi olduğu duyurulur, ve kullanıcılar Şekil türünden nesneleri 'nesne.çiz()' diye kullanabilirler. Gerçek türlerini bilmeden...

Benim de karşıma çoğunlukla böyle sıradüzenler çıkar (basitlik ön planda! :) ): Arayüz sınıfı, ve onu gerçekleştiren alt sınıflar. Çok temiz bir tasarımdır... Bazen bir kaç alt sınıfın ortak özellikleri olur; o zamanda bu ortak davranış aradaki başka bir katmana verilebilir. Ama, o katman ya hâlâ "arayüz" olarak kalmalıdır, ya da bir şekilde gizlenmelidir.

Yani en temizi, sıradüzenin en tepesinde bir arayüz, ve olabildiğince sığ olan kalıtımın alt tarafında da gerçekleştirme sınıfları. Her zaman bu kadar basit olmaz, ama çoğu zaman bu kadar basit olur. :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

Alıntı (acehreli):

>

Soru: Ben Alexandrescu'nun örneğini çalıştıramadım. :D int döndüren bir fonksiyon yazıp onu 'alias this' yapmaya çalıştım ama olmadı. (?)

Herhalde çoklu kalıtım ve arayüz kullanan örneği kasdediyorsunuz. Bu program bende 42 yazıyor ekrana ..

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

D dilinde çoklu kalıtım var mı ki? Yok diye biliyorum.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

Çoklu kalıtımın yalnızca arayüzler için olması önerilir. Bir sınıfın başka sınıflardan oluşması için kullanılmaması iyi olur.

Çünkü kalıtım, "o sınıftan olma" kavramını modeller. O yüzden Araba'yı Motor'dan ve bir DikizAynası'ndan türetmek önerilmez. Eğer yapılabilse (C++'ta yapılabilir, Java'da da yapılamaz), en azından bir kusuru vardır: Araba nesnelerini DikizAyna'sı nesneleriyle bir araya koyabiliriz. Bir kutu dolusu dikiz aynası; ama aralarında bir tanesi kılık değiştirmiş bir Araba! :)

Sınıflar arasında bir "is-a" ("öyledir") ilişkisi varsa kalıtım, "has-a" ("sahiptir") ilişkisi varsa içerme önerilir. "Araba bir Taşıt'tır" onun için Araba Taşıt'tan türer. "Araba DikizAynası'na sahiptir", onun için DikizAynası içerir.

D de bu tür çoklu kalıtıma izin vermez.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

Kalıtım ve tür dönüşümü arasında üstü örtülü bir ilişki vardır: İkisinde de nesneler başka türden nesneler olarak kullanılırlar. Örnekler:

int => long        // temel tür dönüşümü
Kedi => Hayvan     // kalıtım nedeniyle üst türe dönüşüm
BüyükSayı => int   // kullanıcının tanımladığı dönüşüm

O sonuncusu C++'daki tür dönüşümü yükleme örneğidir:

class BuyukSayi
{
/* ... */
   operator int() const;
};

O işleç sayesinde bir BuyukSayi nesnesini bir int'e dönüştürmüş oluruz. Yani bir anlamda BuyukSayi bir int'ten türemiş gibi olur, çünkü bir int'in gerektiği yerde kullanılabilir.

İşte D, birden fazla sınıftan türeme kavramını bu şekilde dolaylı olarak tür dönüşümü ile idare eder. Tam destek vermemesinin baş nedenlerinden birisi bu olanağın sık gerekmemesi, ve kullanımının ve derleyicide gerçekleştirilmesinin sorunlu olmasıdır.

Alexandrescu'nun makalesinde gösterdiği de aslında bir tür dönüşümü:

import std.stdio;

class BüyükSayı
{
   int sayı_ = 42;

   /* sayı_, bu türün kullanıldığı yerlerde bu tür yerine
    * kullanılabilir. Bir anlamda 'int' dönüşümü olur. */
   alias sayı_ this;
}

void foo(int sayı)
{
   writeln(sayı);
}
void main()
{
   foo(new BüyükSayı);
}

Uyarı: Bir sınıfta yalnızca bir tane 'alias this' olabiliyor.

Soru: Ben Alexandrescu'nun örneğini çalıştıramadım. :D int döndüren bir fonksiyon yazıp onu 'alias this' yapmaya çalıştım ama olmadı. (?)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

Yani makaledeki gibi 'alias this''i fonksiyonla kullanamadım. Bu çalışmıyor:

import std.stdio;

class BüyükSayı
{
   int sayı_döndüren_fonksiyon()
   {
       return 42;
   }

   alias sayı_döndüren_fonksiyon this;
}

void foo(int sayı)
{
   writeln(sayı);
}
void main()
{
   foo(new BüyükSayı);
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 20, 2009

Galiba çözdüm: BüyükSayı'nın int'e dönüşümü otomatik değilmiş. Hata mesajı şuydu:

Error: cannot implicitly convert expression (new BüyükSayı) of type deneme.BüyükSayı to int

Tür dönüşümünü 'cast(int)' ile açıkça isteyince çalışıyor:

import std.stdio;

class BüyükSayı
{
   int sayı_döndüren_fonksiyon()
   {
       return 42;
   }

   alias sayı_döndüren_fonksiyon this;
}

void foo(int sayı)
{
   writeln(sayı);
}
void main()
{
   foo(cast(int)new BüyükSayı);
}

İstediğim sonucu veriyor ama güvenli olup olmadığını bilmiyorum.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 24, 2012

Alıntı:

>
interface: arayüz
repeat: tekrarlayarak string oluşturan bir fonksiyon
foreach ve 0..n gibi bir aralık
appender: "sonuna ekleyen" bir tür
foreach ve dizi

Alıntı:

>
> import std.stdio;
> import std.string;
> import std.array;
>
> interface Şekil
> {
>     void çiz();
> }
>
> class YatayÇizgi : Şekil
> {
>     int genişlik_;
>
>     this (int n)
>     {
>         genişlik_ = n;
>     }
>
>     void çiz()
>     {
>         writeln(repeat("-", genişlik_));
>     }
> }
>
> class DikeyÇizgi : Şekil
> {
>     int yükseklik_;
>
>     this (int n)
>     {
>         yükseklik_ = n;
>     }
>
>     void çiz()
>     {
>         foreach(i; 0..yükseklik_) {
>             writeln('|');
>         }
>     }
> }
>
> class Çerçeve : Şekil
> {
>     Şekil[] şekiller_;
>
>     this (int genişlik, int yükseklik)
>     {
>         şekiller_ = new Şekil[0];
>
>         auto sonuna_ekleyici = appender(&şekiller_);
>         sonuna_ekleyici.put(new YatayÇizgi(genişlik));
>         sonuna_ekleyici.put(new DikeyÇizgi(yükseklik));
>         sonuna_ekleyici.put(new YatayÇizgi(genişlik));
>     }
>
>     void çiz()
>     {
>         foreach(şekil; şekiller_) {
>             şekil.çiz();
>         }
>     }
> }
>
> void main ()
> {
>     Çerçeve çerçeve = new Çerçeve(12,5);
>     çerçeve.çiz();
> }
> ```

>

Not:  2012 mart ayında 'std.string' modülünde yer alan 'repeat()' işlevi emekliye ayrılmış. onun yerine 'std.array' modülünde bulunan 'replicate()' işlevini kullanmamız gerekiyor. Kodları deneyecek olan arkadaşlarımın  YatayÇizgi sınıfını aşağıdaki gibi düzenlemeleri gerekmektedir.

class YatayÇizgi : Şekil
{
int genişlik_;

this (int n)
{
genişlik_ = n;
}

void çiz()
{
writeln(replicate("-", genişlik_));
}
}



-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
1 2
Next ›   Last »