Forum: Ders Arası RSS
Yapılar ve "Önceki Değerleri Kilitleyerek Aktarma"
Struct and "Post Blits"
Avatar
Salih Dinçer #1
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Yapılar ve "Önceki Değerleri Kilitleyerek Aktarma"
Merhaba,

Ali hocam, D.ershane'de yapıları anlatırken çok basit ve de yerine göre çok çok önemli olabilecek bir sorun ile çözümüne değinmiş. Hem de çözümü aşağıda göreceğiniz üzere dahili halini de ilerleyen derslerde vermiş. Ancak bu çözüm sınıflarda çalışmadığını belirtmeliyim...

Örneği biraz zenginleştirdim, kısaca çalışan kod şöyle:
import std.conv, std.stdio;
 
struct Öğrenci {
  int numara;
  int[] notlar;
 
  this(this) { notlar = notlar.dup; }
 
  string toString() const {
      bool yazma;
      enum ders { Türkçe, Japonca, Matematik }
      string sonuç = to!string(numara) ~ " numaralı öğrencinin notları: (";
      foreach(adı, notu; notlar) {
          if(yazma) sonuç ~= ", ";
          sonuç ~= to!string(cast(ders)adı) ~ "=" ~ to!string(notu);
          yazma = true;
      }
      return sonuç ~ ")\n";
    }
}
 
void main() {
  auto Ali = Öğrenci(42, [70, 60, 90]);
       Ali.writeln("\tismi: Ali");
  auto Salih = Ali;
       Salih.numara = 41;
       Salih.writeln("\tismi: Salih");
 
  "Ali, Türkçe'den +1 not aldığında notu şu oldu: ".writeln(++Ali.notlar[0]);
  "Salih'e notlarına n'oldu?\n".writeln(Salih);
}
Çıktıyı vermiyorum çünkü denemeli (kurucu satırı aç/kapa yapmalı) ve farkı görmelisiniz. Ama tahmin edeceğiniz üzere, bahsedilen sorun referans üyeler içeren bir yapıyı başkasına kopyaladığınızda aslında her iki yapı tıpkı static olarak işaretlenmiş gibi tek bir değişkeni gösterecektir. O yüzden referans türler kullanırken dikkatli olmalı veya yukarıdaki gibi önlem almalısınız.

Ayrıca burada orijinal ismi "post blits" olan bir şey daha yapılıyor. Hiç bir parametre almayan kurucu işleve this ekleniyor: this(this) { ... } Böylece önceki yapının değerleri aynen aktarılırken ek olarak kurma işlevini genişletiyorsunuz.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
bu çözüm sınıflarda çalışmadığını belirtmeliyim...

Öyle söyleyince bir sorun varmış gibi anlaşılabiliyor. Hayır, sınıflarda çalışmıyor çünkü sınıflarda böyle bir sorun yok. :)

orijinal ismi "post blits"

Onun çoğul kullanımı olduğunu belirtmek gerek. Belgelerde "postblit" diye geçiyor:

  http://dlang.org/struct.html#StructPostblit

Ali
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Sanırım tatilde olduğum sırada es geçtiğim başlıklardan biriydi bu. Fazla irdelemediğimi ve unuttuğumu farkettim! Arzu ederseniz devam edelim...:)

Öncelikle bu örnek şurada geçmişti: http://ddili.org/ders/d/yapilar.html

Bunu sınıf ile yaptığımda (aşağıdaki) sorunun devam ettiğini görüyorum. Acaba opCall() gibi bir şey mi kullanmak lazım? Soruna ise kısaca kod içinde değindim...
import std.conv, std.stdio;
 
class Öğrenci {
  int numara;
  int[] notlar;
 
  //this(this) { notlar = notlar.dup; }/*
  this(int numara, int[] notlar){
    this.numara = numara;
    this.notlar = notlar;
  }//*/
  string toString() const {
      bool yazma;
      enum ders { Türkçe, Japonca, Matematik }
      string sonuç = to!string(numara) ~ " numaralı öğrencinin notları: (";
      foreach(adı, notu; notlar) {
          if(yazma) sonuç ~= ", ";
          sonuç ~= to!string(cast(ders)adı) ~ "=" ~ to!string(notu);
          yazma = true;
      }
      return sonuç ~ ")\n";
    }
}
 
void main() {
  auto Ali = new Öğrenci(42, [70, 60, 90]);
       Ali.writeln("\tismi: Ali");
 
  /* Yukarıda Ali nesnemiz Öğrenci olarak kuruluyor...
   * Buradaki ilk not Türkçe dersinden ve dikkat ilk notu 70
   * Aşağıda ise nesnenin bir kopyası çıkıyor ve farklılık
   * olsun diye numarası 41 yapılıyor...
   */
 
  auto Salih = Ali;
       Salih.numara = 41;
       Salih.writeln("\tismi: Salih");
 
  /* Kurulum işlemleri tamamlanınca Ali'nin notunu arttırıyoruz
   * Ama dikkat, Salih'in notu da değişiyor ve bu sorunu yapıda 
   * this(this) { notlar = notlar.dup; } <-- satırı ile halletmiştik...
   */
 
  "Ali, Türkçe'den +1 not aldığında notu şu oldu: ".writeln(++Ali.notlar[0]);
  "Salih'e notlarına n'oldu?\n".writeln(Salih);
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yapılar değer türü. Yani, nesneleri kopyalandıklarında veya atandıklarında soldaki nesne sağdakinden farklı bir nesne oluyor.

Ancak, senin de burada belirttiğin gibi, kendileri farklı nesne olsalar da üyelerini paylaşmaya devam edebiliyorlar.

Sınıflarda ise durum daha vahim: Kopyalama veya atama söz diziminde ikinci bir nesne yok. İki değişken aynı nesneye eriştirmey başlıyorlar. (Bu, Java (ve sanırım C#) türleri gibi.)

Sınıflarda çok önemli ve farklı iki kavram var:

  • Sınıf nesnesi: new ile oluşturulur ve hiçbir zaman kendi ismi yoktur.

  • Sınıf değişkeni: Sınıf nesnesine erişim sağlar. Kod içinde hep bunu kullanırız.

Şuradaki "Sınıf nesneleri ve değişkenleri", "Kopyalama", ve "Atama" başlıkları çok önemli:

  http://ddili.org/ders/d/siniflar.html

(Aslında o bölümü biraz daha geliştirdim ve düzelttim ama daha siteye koymadım.)

Ali
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Aslında o bölümü biraz daha geliştirdim ve düzelttim ama daha siteye koymadım.

Örneğin, oradaki kopyalama örneğini şöyle değiştirmişim:
class Sınıf
{
    Yapı   yapıNesnesi;
    char[] dizgi;
    int    tamsayı;
 
// ...
 
    this(Yapı yapıNesnesi, const char[] dizgi, int tamsayı)
    {
        this.yapıNesnesi = yapıNesnesi;
        this.dizgi       = dizgi.dup;
        this.tamsayı     = tamsayı;
    }
 
    Sınıf dup()
    {
        return new Sınıf(yapıNesnesi, dizgi, tamsayı);
    }
}

Ali
Avatar
Salih Dinçer #6
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #4
Anlıyorum hocam...

Aslında bu şekilde nesne kurulumunu genelde kullanmıyoruz ama bilmemizin çok önemli olduğunu düşünüyorum. Olur ya, benzer bir işlem yaparız ve kafa patlatırız neden hiç bir şey değişmiyor diye...:)

Teşekkürler...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
bilmemizin çok önemli olduğunu düşünüyorum.

Kesinlikle! :)

C++'tan gelenler her şeyi değer türü olarak görmeye alışmışlardır, Java gibi başka dillerden gelenler de herşeyi referans türü olarak görmeye alışmışlardır. D'de yapılar değer türü, sınıflar referans türü.

Baştan benim kafamı çok karıştırmıştı. :)

Ali
Avatar
mert #8
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
Salih merhaba,
 
...//
 string toString() const  // yerine
//.... 
#3 numaralı mesajındaki örneğini denemek isteyen arkadaşlarımız için, haddim olmayarak minik bir hatırlatmada bulunmak isterim:
string toString() işlevi override olarak işaretlenmelidir.
 
...//
override string toString() const  // olmalı. Çünkü bir önceki örneğimizde yapı içinde
                                  // toString() işlevi kullanılıyor. Bu örnekte ise class 
                                  // kullanıyoruz. class toString() işlevini Object 
                                  // sınıfından otomatik olarak alıyor.
                                  // O nedenle kendi türümüz için Object'ten gelen  toString() 
                                  // işlevini baskılamamız gerekiyor.
//.... 
mert
Bu mesaj 2 defa değişti; son değiştiren: mert; zaman: 2012-10-28, 19:47.
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-21, 19:26:03 (UTC -08:00)