Thread overview
Tek Yönlü Kapsüllemede auto Sızması
Nov 04, 2021
Salih Dincer
Nov 05, 2021
Salih Dincer
Nov 05, 2021
Salih Dincer
Nov 05, 2021
Ferhat Kurtulmuş
Nov 05, 2021
Ferhat Kurtulmuş
Nov 05, 2021
Ali Çehreli
Nov 05, 2021
Salih Dincer
November 04, 2021

Merhaba,

Belki bu, ustalar için şaşırtıcı değildir ama olayı kavramamda yardımcı olursanız benim için büyük bir adım olacak. Şimdiden teşekkürler...

Aşağıdaki kodda tek yönlü (get'li) bir kapsülleme yaptım. Eğer auto kullanmaya devam edersem hiçbir 'undefined ' hatası almıyoruz; ver.1 için konuşuyorum çünkü diğerinde yapıyı sınıf dışına alıyoruz. Soru geliyor... 😀

Nasıl olur da main(), Point'den haberdar değilken, auto'lar ile sınıf tanımlandıktan sonra sanki ver.2'miş gibi program derlenebiliyor?

Ya da sanki Point türünde global bir değişkenmiş gibi onunla işlem yapabiliyorum? Bu nasıl olur, beklenmedik bir durum, auto type sızması değil de nedir!

class Foo { // ver.1
    struct Point
    {
        int x, y;
    }

//class Foo { // ver.2
    Point bar;

    this()
    {
        bar = Point(10, 20);
    }

    Point get()
    {
        return bar;
    }
}

void main()
{
    auto foo = new Foo();
    auto point = foo.get;
         point.x++;

    int normal_mi = point.x + 30;
    assert(normal_mi == 41);
}
November 05, 2021

On Thursday, 4 November 2021 at 21:43:16 UTC, Salih Dincer wrote:

>

Merhaba,

Tekrar Merhaba,yeni bir şey var (!) ve de 1 + 1 modül; public/private olaylarını görebilmem için. Bu kapsülleme de neyi yanlış yapıyor olabilirim?

Çünkü Point yapısına erişememem ve içeriğini sadece dolaylı yoldan değiştirebilmem gerekiyor. Aşağıdaki kodlarda her ikisi de mümkün ve şu derleme parametrelerine sahip:

ldc2 -w -O -of"capsul" "capsul.d" kapsul.d

module capsul;
import kapsul, std.stdio;

void main()
{
    auto foo = new Foo(10, 20);
    foo.writeln; // Point(10, 20);

    // get():
    auto point = foo.get;
         point.x += 10;
    foo.writeln; // Point(20, 20);

    // set():
    auto bar = new Foo(1, 1);
         bar.set(point);
    foo.writeln; // Point(20, 20);
}

Dikkat: point'i işaretçi (pointer) kullanarak get/set yapıyorum...

module kapsul;
import std.format;

class Foo {
    private struct Point
    {
        int x, y;
    }

    private Point point;

    this(int x, int y)
    {
        point = Point(x, y);
    }

    Point* get()
    {
        return &point;
    }

    void set(Point* point)
    {
        this.point.x = point.x;
        this.point.y = point.y;
    }

    override string toString()
    {
        return point.format!"%s";
    }
}
November 05, 2021

On Friday, 5 November 2021 at 08:34:43 UTC, Salih Dincer wrote:

>

...
public/private olaylarını görebilmem için. Bu kapsülleme de neyi yanlış yapıyor olabilirim?
...

private'i yapı içene aldığımda şimdi çalışıyor. O yüzden 2. mesajımı geri aldım ama hala Point'in varlığının auto ile temsil edilebilmesi bana ilginç geliyor.

Sanırım [0, 1, 2, 3].filter!("a > 0") yaptığımızda nasıl bir FilterResult!(__lambda1, int[]) dönüyorsa bu da böyle bir şey...?

class Foo {
    struct Point
    {
       private int x, y; // Artık doğrudan erişeme kapalı
    }

    private Point point; // ve bu da doğru ve çalışıyor...

    this(int x, int y)
    {
        point = Point(x, y);
    }
/***
November 05, 2021

On Friday, 5 November 2021 at 12:53:40 UTC, Salih Dincer wrote:

>

On Friday, 5 November 2021 at 08:34:43 UTC, Salih Dincer wrote:

>

...
public/private olaylarını görebilmem için. Bu kapsülleme de neyi yanlış yapıyor olabilirim?
...

private'i yapı içene aldığımda şimdi çalışıyor. O yüzden 2. mesajımı geri aldım ama hala Point'in varlığının auto ile temsil edilebilmesi bana ilginç geliyor.

Sanırım [0, 1, 2, 3].filter!("a > 0") yaptığımızda nasıl bir FilterResult!(__lambda1, int[]) dönüyorsa bu da böyle bir şey...?

class Foo {
    struct Point
    {
       private int x, y; // Artık doğrudan erişeme kapalı
    }

    private Point point; // ve bu da doğru ve çalışıyor...

    this(int x, int y)
    {
        point = Point(x, y);
    }
/***

Class skopu içindeki Point tipinden değişken class üye fonksiyonu ile döndürülürse "Voldemort tipi" oluyor. Harry Potter'dan evet :)

https://wiki.dlang.org/Voldemort_types

Burada detayları var. D'de özellikle range tiplerinin bu şekilde return edilmesi çok yaygın. Phobos bunlarla dolu. Örneğin parametre olarak Associative Array alan byKey ve byKeyValue fonksiyonları aslında birer Range struct'ı döndürüyor. Ama tıpkı Voldemort gibi adlarını telaffuz edemezssin :)

November 05, 2021

On Friday, 5 November 2021 at 13:11:42 UTC, Ferhat Kurtulmuş wrote:

>

On Friday, 5 November 2021 at 12:53:40 UTC, Salih Dincer wrote:

>

[...]

Class skopu içindeki Point tipinden değişken class üye fonksiyonu ile döndürülürse "Voldemort tipi" oluyor. Harry Potter'dan evet :)

https://wiki.dlang.org/Voldemort_types

Burada detayları var. D'de özellikle range tiplerinin bu şekilde return edilmesi çok yaygın. Phobos bunlarla dolu. Örneğin parametre olarak Associative Array alan byKey ve byKeyValue fonksiyonları aslında birer Range struct'ı döndürüyor. Ama tıpkı Voldemort gibi adlarını telaffuz edemezssin :)
Yanlış anlaşılmasın, bu class dahil struct ve fonksiyon dahil her scope için geçerlidir.

November 05, 2021
On 11/4/21 2:43 PM, Salih Dincer wrote:

> Nasıl olur da main(), Point'den haberdar değilken

Ferhat Kurtulmuş zaten yanıtlamış. Ben aklıma gelen uzaktan ilgili başka konulara da değineceğim. (esin

1) D'nin özellikle C++ programcılarını şaşırtan bir özelliği, `private`ın "modüle özel" anlamına gelmesidir. Eğer program gösterildiği gibi tek modüldeyse, main Foo'nun içindeki her şeye erişebilir:

class Foo {
private:      // <-- Bu modülü ırgalamaz :)
     struct Point
     {
         int x, y;
     }
}

void main()
{
  Foo.Point point;  // Çalıştı
}

Ama fonksiyon içindeki tanımlara zaten erişemeyiz. (Bu, Ferhat Kurtulmuş'un söylediği Voldemort türünün örneği olur.)

// Dönüş türü auto olmalıdır çünkü içerideki tanım
// burada telaffuz edilemez.
auto foo() {
  struct Point {}  // Dışarıdan erişilemez ama
                   // bütün işlevselliği ile
                   // kullanılabilir

  return Point();
}

2) D'nin auto'su da C++'tan farklıdır: C++'ta "otomatik çıkarsama" anlamına gelir. D de ise başka hiçbir anahtar sözcük kullanılamayan durumlarda yer tutsun diye kullanılır ve C'den beri bilinen ama artık kullanılmayan "yaşamı otomatik olarak sonlansın" anlamına gelir.

  const a = 42;  // D'de auto gerekmez
  auto b = 43;

Ali


November 05, 2021

Konu işlendi ve kapandı. Ancak yarım kaldı!

Bu leziz alıştırmayı paylaşmadan edemiyorum:

import std;

struct Point { int x, y; }

class Cap {
    Point point;

    this(int x, int y)
    {
        point = Point(x, y);
    }

    Point * get()
    {
        return &point;  /* eğer burda adresini
        döndürmesek, set() vasıtasıyla yapılan
        her değişiklik kapsüllenmiş verileri
        temsil etmeyecek/göstermeyecek...*/
    }

    void set(Point * point)  /* v1 */
    {
        this.point.x = point.x;
        this.point.y = point.y;
    }

    void set(Point point)  /* v2 */
    {
        this.point = point;
    }

    string hip()
    {
        return point.format!"%s";
    }

    ~this() {
      writefln("%d:%d noktası yok!", point.x, point.y);
    }
}

void main()
{
    // önce yedekleme amaçlı bir işaretçi olsun:
    Point * p_backup;

    auto bar = Point(10, 10);  // ve yeni bir nokta

    with(new Cap(1, 1))
    {
      hip.writeln(" ile kurduk...");
      p_backup = get(); // 1:1 noktasını yedekledik
      set(bar); // şimdi Cap.point 10:10'da

      hip.writeln(" == ", *p_backup);

      assert(point == *p_backup); /* hata yok,
      çünkü:                       */
      assert(&point == p_backup); /* bu da
      çökmedi, kodlar istediğimiz gibi */
    }
    writeln;
    // yeni bir Cap:
    auto ikiYirmi = new Cap(2, 20);
    writeln(*ikiYirmi.get, " 2. kapsül...");
    writeln(*p_backup, "\n");

    //ikiYirmi.set(p_backup); // bu set() v1 çalışır!
}

/* ÇIKTISI:
Point(1, 1) ile kurduk...
Point(10, 10) == Point(10, 10)

Point(2, 20) 2. kapsül...
Point(10, 10)

10:10 noktası yok!
2:20 noktası yok!
*/

Private yok, soru yok! Voldemort da yok 😀
Ama şu var:

Son satır koda dahil edilince işaretçi alan set() çalışır ve bellekteki her iki yapı da yok olmadan önce aynı noktayı/veriyi gösterir.

Ve sadece birbirlerinin kopyasıdır yani farklı adreslerdeki aynı veridir.