Nesne ömrü - Object lifetime

Olarak nesne yönelimli programlama (OOP), nesne süresi (ya da yaşam döngüsü , bir bölgesinin) bir nesne , bir nesnenin yaratılmasına ve imha arasında geçen süredir. Nesne ömrüne ilişkin kurallar, diller arasında, bazı durumlarda belirli bir dilin uygulamaları arasında önemli ölçüde farklılık gösterir ve belirli bir nesnenin ömrü, programın bir çalışmasından diğerine değişebilir.

Bazı durumlarda ile kullanım süresi çakıştığını nesne değişken ömrü (hem değeri olarak bu nesneyle bir değişkenin statik değişkenler ve otomatik değişkenler ), ancak genel bir amacı, kullanım ömrü herhangi bir değişkenin ömrü bağlı değildir. Çoğu durumda - ve varsayılan olarak birçok nesne yönelimli dilde , özellikle de çöp toplama (GC) kullananlarda - nesneler öbek üzerinde tahsis edilir ve nesne ömrü, belirli bir değişkenin ömrü tarafından belirlenmez: bir değişkenin değeri bir nesneyi tutmak, aslında nesnenin kendisine değil, nesneye yapılan bir başvuruya karşılık gelir ve değişkenin yok edilmesi, alttaki nesneyi değil, yalnızca referansı yok eder.

genel bakış

Temel nesne ömrü fikri basit olsa da - bir nesne oluşturulur, kullanılır, sonra yok edilir - ayrıntılar diller arasında ve belirli bir dilin uygulamaları içinde büyük ölçüde değişir ve bellek yönetiminin nasıl uygulandığına yakından bağlıdır . Ayrıca, adımlar arasında ve dil düzeyindeki kavramlar ile uygulama düzeyindeki kavramlar arasında birçok ince ayrım çizilir. Terminoloji nispeten standarttır, ancak hangi adımların belirli bir terime karşılık geldiği diller arasında önemli ölçüde farklılık gösterir.

Terimler genellikle zıt anlamlı çiftler halinde gelir; biri yaratma kavramı için, diğeri başlatma/sonlandırma veya yapıcı/yıkıcı gibi karşılık gelen yok etme kavramı için . Yaratma/yok etme çifti, diğer terimlerin yanı sıra başlatma/sonlandırma olarak da bilinir . Terimleri ayırma ve serbest bırakma ya da azat nesne oluşturma ve yok sırasıyla yaratma ve yıkım basitçe bellek yerleştirme ve boşaltmaları ve ayırma / serbest bırakma daha uygun kabul edilir adımları önemli ölçüde daha fazla dahil olsa da, bellek yönetimi ile benzer şekilde kullanılır.

determinizm

Önemli bir ayrım, bir nesnenin ömrünün deterministik mi yoksa deterministik mi olmadığıdır. Bu, dile göre değişir ve dil içinde bir nesnenin bellek tahsisine göre değişir ; nesne ömrü, değişken yaşam süresinden farklı olabilir.

İle Nesneler statik hafıza tahsisi , özellikle saklanan nesnelerin statik değişkenler ve sınıflar modülleri (sınıflar veya modüller ise kendileri itiraz ediyor ve statik olarak ayrılan), birçok dilde ince olmayan determinizm vardır: onların yaşam boyu görünürken çakışır için çalışma zamanında ile programın, yaratma ve yok etme sırası – hangi statik nesnenin önce yaratıldığı, hangisinin ikinci, vb. – genellikle deterministik değildir.

İle nesneler için otomatik bellek ayırma ya da dinamik bellek ayırma , nesne oluşturma, genel bir amacı, açık bir şekilde (örneğin, üzerinden olarak oluşturulur ya açık olduğunda, deterministik olur new, ya da dolaylı olarak değişken kullanım ömrünün başlangıcında C ++ veya Java) özellikle kapsamı bir bölgesinin bildirimde olduğu gibi otomatik değişken girilir. Bununla birlikte, nesne imhası değişir – bazı dillerde, özellikle C++, otomatik ve dinamik nesneler, kapsam çıkışı, açık imha ( manuel bellek yönetimi aracılığıyla ) veya referans sayısının sıfıra ulaşması gibi belirli zamanlarda yok edilir ; C#, Java ve Python gibi diğer dillerde ise, bu nesneler çöp toplayıcıya bağlı olarak deterministik olmayan zamanlarda yok edilir ve imha sırasında nesne dirilişi gerçekleşebilir, bu da kullanım ömrünü uzatır.

Çöp toplanmış dillerde, nesneler, genellikle otomatik olarak tahsis edilen (yığında veya bir kayıtta) ilkel değerlere sahip otomatik değişkenlerin aksine, başlangıçta otomatik bir değişkene bağlı olsalar bile genellikle dinamik olarak (yığın üzerinde) tahsis edilir. Bu, nesnenin bir işlevden ("kaçış") yok edilmeden döndürülmesine olanak tanır. Bununla birlikte, bazı durumlarda bir derleyici optimizasyonu mümkündür, yani kaçış analizi yapmak ve kaçışın mümkün olmadığını kanıtlamak ve böylece nesne yığına tahsis edilebilir; bu Java'da önemlidir. Bu durumda, nesne imhası derhal gerçekleşir - eğer ulaşılamazsa, muhtemelen değişkenin ömrü boyunca (kapsamının bitiminden önce) bile.

Karmaşık bir durum, nesnelerin önceden oluşturulabildiği veya yeniden kullanılabildiği bir nesne havuzunun kullanılmasıdır ve bu nedenle, görünen yaratma ve yok etme, bir nesnenin gerçek yaratımı ve imhasına karşılık gelmeyebilir, yalnızca oluşturma ve sonlandırma için (yeniden)başlatma işlemine karşılık gelebilir. yıkım. Bu durumda hem yaratma hem de yok etme deterministik olmayabilir.

adımlar

Nesne oluşturma iki işleme ayrılabilir: bellek ayırma ve başlatma , burada başlatma hem nesne alanlarına değer atamayı hem de muhtemelen rastgele başka kod çalıştırmayı içerir. Bunlar, daha sonra dil düzeyinde ayrımlar olsa da, bir değişkenin bildirimi ve tanımı arasındaki ayrıma kabaca benzeyen uygulama düzeyindeki kavramlardır . Bir değişkene bağlı bir nesne için, bildirim bellek ayırmaya (nesne için yer ayırma) ve başlatma için tanımlamaya (değer atama) derlenebilir, ancak bildirimler yalnızca derleyici kullanımı için de olabilir ( ad çözümlemesi gibi ), doğrudan derlenmiş koda karşılık gelmez.

Benzer şekilde, nesne imhası, ters sırada iki işleme ayrılabilir: sonuçlandırma ve belleğin yeniden dağıtılması. Bunlar, değişkenler için benzer dil düzeyinde kavramlara sahip değildir: değişken yaşam süresi örtük olarak sona erer (otomatik değişkenler için, yığın çözmede; statik değişkenler için, program sonlandırıldığında) ve şu anda (veya daha sonra, uygulamaya bağlı olarak) bellek serbest bırakılır, ancak genel olarak herhangi bir sonuçlandırma yapılmamaktadır. Ancak, bir nesnenin ömrü bir değişkenin ömrüne bağlıysa, değişkenin ömrünün sonu nesnenin sonlandırılmasına neden olur; bu, C++'da standart bir paradigmadır.

Bunlar birlikte dört uygulama düzeyinde adım sağlar:

tahsis, başlatma, sonuçlandırma, serbest bırakma

Bu adımlar, dil çalışma zamanı, yorumlayıcı veya sanal makine tarafından otomatik olarak yapılabilir veya programcı tarafından bir alt programda somut olarak yöntemlerle manuel olarak belirtilebilir - bunun sıklığı adımlar ve diller arasında önemli ölçüde değişir. Başlatma, sınıf tabanlı dillerde çok yaygın olarak programcı tarafından belirlenirken, katı prototip tabanlı dillerde başlatma, kopyalama yoluyla otomatik olarak yapılır. Sonlandırma, deterministik yıkıma sahip dillerde, özellikle de C++'da çok yaygındır, ancak çöpten toplanan dillerde çok daha az yaygındır. Tahsis daha nadiren belirtilir ve serbest bırakma genellikle belirtilemez.

Oluşturma ve yok etme sırasındaki durum

Önemli bir incelik, bir nesnenin oluşturma veya yok etme sırasındaki durumu ve oluşturma veya yok etme başarısız olması gibi hataların meydana geldiği veya istisnaların ortaya çıktığı durumları ele almaktır. Açıkça söylemek gerekirse, bir nesnenin ömrü, tahsis tamamlandığında başlar ve serbest bırakma başladığında sona erer. Bu nedenle, başlatma ve sonlandırma sırasında bir nesne canlıdır, ancak tutarlı bir durumda olmayabilir - sınıf değişmezlerinin başlatmanın önemli bir parçası olmasını sağlamak - ve başlatmanın tamamlandığı andan sonlandırmanın başladığı zamana kadar olan süre, nesnenin hem canlı olduğu hem de beklendiği zamandır. tutarlı bir durumda olmak.

Oluşturma veya yok etme başarısız olursa, hata raporlaması (genellikle bir istisna oluşturarak) karmaşık olabilir: nesne veya ilgili nesneler tutarsız bir durumda olabilir ve imha durumunda - bu genellikle dolaylı olarak ve dolayısıyla belirtilmemiş bir ortamda gerçekleşir - hataların üstesinden gelmek zor olabilir. Tersi konu – giden istisnalar değil, gelen istisnalar – istisna işleme sırasında, farklı davranışlar istenebilirken meydana gelirse oluşturma veya yok etmenin farklı mı davranacağıdır.

Diğer bir incelik ise , ömrü programın çalışma süresiyle çakışan statik değişkenler için oluşturma ve yok etme olduğunda - oluşturma ve yok etme normal program yürütme sırasında mı yoksa normal yürütmeden önce ve sonra özel aşamalarda mı - ve nesnelerin programda nasıl yok edildiğidir. program olağan veya tutarlı bir durumda olmadığında sonlandırma. Bu, program sonlandırıldığında çok fazla çöp olabileceğinden, özellikle çöpten toplanan diller için bir sorundur.

Sınıf tabanlı programlama

Sınıf tabanlı programlamada nesne oluşturma, örnekleme ( bir sınıfın örneğini oluşturma) olarak da bilinir ve oluşturma ve yok etme , yapıcı ve yok edici veya başlatıcı ve sonlandırıcı olarak bilinen yöntemlerle kontrol edilebilir . Bu nedenle, yaratma ve yok etme aynı zamanda inşa ve yıkım olarak da bilinir ve bu yöntemler çağrıldığında bir nesnenin inşa edilmiş veya tahrip edilmiş ("yok edilmemiş") olduğu söylenir - sırasıyla, bu yöntemler çağrıldığında başlatılır veya sonlandırılır .

Bu yöntemler arasındaki ilişki karmaşık olabilir ve bir dilin hem yapıcıları hem de başlatıcıları (Python gibi) veya hem yıkıcıları hem de sonlandırıcıları ( C++/CLI gibi ) olabilir veya "yıkıcı" ve "sonlandırıcı" terimleri dil- düzey yapıya karşı uygulamaya karşı (C#'a karşı CLI'de olduğu gibi).

Temel bir ayrım, nesne oluşturulana kadar kullanılabilir bir nesne (sınıf örneği) olmadığından, yapıcıların sınıf yöntemleri olmasıdır, ancak diğer yöntemler (yıkıcılar, başlatıcılar ve sonlandırıcılar), bir nesne oluşturulduğundan örnek yöntemlerdir. Ayrıca, yapıcılar ve başlatıcılar argüman alabilirken, yıkıcılar ve sonlandırıcılar genellikle örtük olarak çağrıldıkları için genellikle almazlar.

Yaygın kullanımda, bir yapıcı, bir nesne oluşturmak için doğrudan kullanıcı kodu tarafından doğrudan çağrılan bir yöntemdir, "yıkıcı" ise, deterministik nesne ömürleri olan dillerde nesne imhası üzerine (genellikle örtük, ancak bazen açıkça) çağrılan alt yordamdır - arketip C++'dır. – ve "sonlandırıcı", deterministik olmayan nesne ömrüne sahip dillerde nesne imhasında çöp toplayıcı tarafından örtük olarak çağrılan alt yordamdır – arketip Java'dır.

Sonlandırma sırasındaki adımlar bellek yönetimine bağlı olarak önemli ölçüde değişir: manuel bellek yönetiminde (C++ veya manuel referans sayımında olduğu gibi), referansların programcı tarafından açıkça yok edilmesi gerekir (referanslar temizlendi, referans sayıları azaltıldı); otomatik referans sayımında, bu da sonlandırma sırasında olur, ancak otomatiktir (Python'da olduğu gibi, programcı tarafından belirlenen sonlandırıcılar çağrıldıktan sonra meydana geldiğinde); ve çöp toplama takibinde bu gerekli değildir. Bu nedenle, otomatik referans sayımında, programcı tarafından belirlenen sonlandırıcılar genellikle kısadır veya yoktur, ancak önemli işler hala yapılabilirken, çöp toplayıcıları izlemede sonlandırma genellikle gereksizdir.

Kaynak yönetimi

Nesnelerin deterministik yaşam sürelerine sahip olduğu dillerde, nesne yaşam süresi kaynak yönetimini bindirmek için kullanılabilir : buna Resource Acquisition Is Initialization (RAII) deyimi denir : kaynaklar başlatma sırasında edinilir ve sonlandırma sırasında serbest bırakılır. Özellikle çöp toplama nedeniyle nesnelerin deterministik olmayan yaşam sürelerine sahip olduğu dillerde, bellek yönetimi genellikle diğer kaynakların yönetiminden ayrı tutulur.

nesne oluşturma

Tipik durumda, süreç aşağıdaki gibidir:

  • Bir nesnenin boyutu hesaplamak - boyutu çoğunlukla olduğu gibi aynı sınıf ama değişebilir. Söz konusu nesne bir sınıftan değil, bunun yerine bir prototipten türetildiğinde , bir nesnenin boyutu genellikle yuvalarını tutan dahili veri yapısının (örneğin bir karma) boyutudur.
  • tahsis – mümkünse önceden bilmek, bir nesnenin boyutu artı daha sonra büyüme ile bellek alanı tahsis etmek
  • bağlama yöntemleri – bu genellikle ya nesnenin sınıfına bırakılır ya da gönderim zamanında çözülür , ancak yine de bazı nesne modellerinin oluşturma sırasında yöntemleri bağlaması mümkündür.
  • üst sınıfın bir başlatma kodunu (yani, yapıcı ) çağırmak
  • oluşturulmakta olan sınıfın başlatma kodunu çağırma

Bu görevler bir kerede tamamlanabilir, ancak bazen yarım kalır ve görevlerin sırası değişebilir ve birkaç garip davranışa neden olabilir. Örneğin, çoklu kalıtımda , hangi başlatma kodunun önce çağrılması gerektiği, yanıtlanması zor bir sorudur. Ancak, üst sınıf kurucuları, alt sınıf kurucularından önce çağrılmalıdır.

Her nesneyi bir dizinin elemanı olarak yaratmak karmaşık bir problemdir. Bazı diller (örn. C++) bunu programcılara bırakır.

Taşıma istisnaları genellikle durumlar atma uygulanması geçerli nesne devletler dayanır çünkü bir nesnenin yaratılış ortasında özellikle problemlidir. Örneğin, bellekte boş alan olmaması nedeniyle bir nesnenin tahsisi bundan önce başarısız olduğunda, bir istisna nesnesi için yeni bir alan tahsis etmenin bir yolu yoktur. Bu nedenle, OO dillerinin uygulamaları, kaynak sıkıntısı olduğunda bile istisnaların oluşturulmasına izin verecek mekanizmalar sağlamalı ve programcılar veya tür sistemi, kodlarının istisna açısından güvenli olmasını sağlamalıdır . Bir istisnayı yaymak, kaynakları tahsis etmekten daha olasıdır. Ancak nesne yönelimli programlamada, nesne oluşturma başarısız olabilir, çünkü bir nesne oluşturmak, genellikle her yapıcı argüman kombinasyonu için geçerli olmayan sınıf değişmezlerini oluşturmalıdır. Böylece, yapıcılar istisnalar oluşturabilir.

Anahtar fabrika kalıbı bu tür bir cismin oluşturulması için kod bir nesnenin belirli bir uygulama ayrıştırmak için bir yöntemdir.

oluşturma yöntemleri

Nesne oluşturma yöntemi diller arasında farklılık gösterir. Bazı sınıf tabanlı dillerde, yapıcı olarak bilinen özel bir yöntem , bir nesnenin durumunu doğrulamaktan sorumludur. Tıpkı sıradan yöntemlerde olduğu gibi, belirtilen farklı niteliklerle bir nesnenin oluşturulabilmesi için yapıcılar aşırı yüklenebilir . Ayrıca yapıcı, değişmez nesnelerin durumunu ayarlamak için tek yerdir . Bir kopya oluşturucu , yapıcı sınıfıyla aynı türde mevcut bir nesnenin (tek) parametresini alan ve parametre olarak gönderilen nesnenin bir kopyasını döndüren bir yapıcıdır.

Objective-C gibi diğer programlama dilleri, yapıcı türü yöntemleri içerebilen sınıf yöntemlerine sahiptir, ancak yalnızca nesnelerin başlatılmasıyla sınırlı değildir.

C++ ve Java , adlandırılmış kurucular sağlamadıkları için eleştirilmiştir; bir kurucu her zaman sınıfla aynı ada sahip olmalıdır. Programcı aynı argüman tiplerine sahip iki kurucu sağlamak istiyorsa, örneğin kartezyen koordinatlardan veya kutupsal koordinatlardan bir nokta nesnesi oluşturmak istiyorsa, her ikisi de iki kayan noktalı sayı ile temsil edilecekse bu sorunlu olabilir . Objective-C, programcının başlatma yöntemleriyle, örneğin +newPointWithX:andY: ve +newPointWithR:andTheta: ile bir Point sınıfı oluşturabilmesiyle bu sorunu aşabilir . C++'da, statik üye işlevleri kullanılarak benzer bir şey yapılabilir.

Bir yapıcı , özellikle işlevsel dillerde, etiketli bir birliğin değerini oluşturmak için kullanılan bir işleve de başvurabilir .

nesne imha

Genellikle bir nesne kullanıldıktan sonra, diğer programların veya nesnelerin o nesnenin yerini alması için yer açmak için bellekten kaldırılır. Bununla birlikte, yeterli bellek varsa veya bir programın çalışma süresi kısaysa, nesne imhası gerçekleşmeyebilir, işlemin sonlandırılmasında bellek yalnızca serbest bırakılır. Bazı durumlarda nesne imhası, özellikle çöpten toplanan dillerde veya "nesne" aslında düz eski bir veri yapısıysa, belleğin yeniden tahsis edilmesini içerir . Diğer durumlarda, özellikle üye nesneleri yok etme (manuel bellek yönetiminde) veya referans sayılarını azaltmak için nesneden diğer nesnelere referansları silme (referans sayımında) olmak üzere, ayırmadan önce bazı işler gerçekleştirilir. Bu otomatik olabilir veya nesne üzerinde özel bir imha yöntemi çağrılabilir.

Belirleyici nesne ömrüne sahip sınıf tabanlı dillerde, özellikle C++, bir yıkıcı , bir sınıfın bir örneği silindiğinde, bellek serbest bırakılmadan önce çağrılan bir yöntemdir . C++'da yıkıcılar, yapıcılardan çeşitli şekillerde farklıdır: aşırı yüklenemezler, argümanları olmamalıdır, sınıf değişmezlerini sürdürmeleri gerekmez ve istisnalar atarlarsa programın sonlandırılmasına neden olabilirler.

Gelen çöp toplama artık çalışan kod tarafından ulaşılabilir zaman dillere, nesneler yok edilebilir. Sınıf tabanlı GCed dillerde, yıkıcılar analog olan finalizers , bir nesne çöp toplama önce denir. Çöp toplama öngörülemez olduğundan ve C++ yıkıcılarından önemli ölçüde daha az kullanıldığından ve daha az karmaşık olduğundan, bunların öngörülemeyen bir zamanda ve öngörülemeyen bir sırada çalışması farklıdır. Bu tür dillere örnek olarak Java , Python ve Ruby verilebilir .

Bir nesneyi yok etmek, nesneye yapılan tüm referansların geçersiz olmasına ve manuel bellek yönetiminde mevcut referansların sarkan referanslara dönüşmesine neden olur . Çöp toplamada (hem izleme çöp toplama hem de referans sayımı), nesneler yalnızca kendilerine referans olmadığında yok edilir, ancak sonlandırma nesneye yeni referanslar oluşturabilir ve sarkan referansları önlemek için referansların geçerli kalması için nesne dirilişi gerçekleşir.

Örnekler

C++

class Foo {
 public:
  // These are the prototype declarations of the constructors.
  Foo(int x);
  Foo(int x, int y);    // Overloaded Constructor.
  Foo(const Foo &old);  // Copy Constructor.
  ~Foo();               // Destructor.
};

Foo::Foo(int x) {
  // This is the implementation of
  // the one-argument constructor.
}

Foo::Foo(int x, int y) {
  // This is the implementation of
  // the two-argument constructor.
}

Foo::Foo(const Foo &old) {
  // This is the implementation of
  // the copy constructor.
}

Foo::~Foo() {
  // This is the implementation of the destructor.
}

int main() {
  Foo foo(14);       // Call first constructor.
  Foo foo2(12, 16);  // Call overloaded constructor.
  Foo foo3(foo);     // Call the copy constructor.

  // Destructors called in backwards-order
  // here, automatically.
}

Java

class Foo
{
    public Foo(int x)
    {
        // This is the implementation of
        // the one-argument constructor
    }

    public Foo(int x, int y)
    {
        // This is the implementation of
        // the two-argument constructor
    }

    public Foo(Foo old)
    {
        // This is the implementation of
        // the copy constructor
    }

    public static void main(String[] args)
    {
        Foo foo = new Foo(14); // call first constructor
        Foo foo2 = new Foo(12, 16); // call overloaded constructor
        Foo foo3 = new Foo(foo); // call the copy constructor
        // garbage collection happens under the covers, and objects are destroyed
    }
}

C#

namespace ObjectLifeTime 
{
class Foo
{
    public Foo()
    {
        // This is the implementation of
        // default constructor.
    }

    public Foo(int x)
    {
        // This is the implementation of
        // the one-argument constructor.
    }
     ~Foo()
    {
        // This is the implementation of
        // the destructor.
    }
 

    public Foo(int x, int y)
    {
        // This is the implementation of
        // the two-argument constructor.
    }
 
    public Foo(Foo old)
    {
        // This is the implementation of
        // the copy constructor.
    }
 
    public static void Main(string[] args)
    {
        Foo defaultfoo = new Foo(); // Call default constructor
        Foo foo = new Foo(14); // Call first constructor
        Foo foo2 = new Foo(12, 16); // Call overloaded constructor
        Foo foo3 = new Foo(foo); // Call the copy constructor
    }
}
}

Amaç-C

#import <objc/Object.h>

@interface Point : Object
{
   double x;
   double y;
}

//These are the class methods; we have declared two constructors
+ (Point *) newWithX: (double) andY: (double);
+ (Point *) newWithR: (double) andTheta: (double);

//Instance methods
- (Point *) setFirstCoord: (double);
- (Point *) setSecondCoord: (double);

/* Since Point is a subclass of the generic Object 
 * class, we already gain generic allocation and initialization
 * methods, +alloc and -init. For our specific constructors
 * we can make these from these methods we have
 * inherited.
 */
@end
 
@implementation Point

- (Point *) setFirstCoord: (double) new_val
{
   x = new_val;
}

- (Point *) setSecondCoord: (double) new_val
{
   y = new_val;
}

+ (Point *) newWithX: (double) x_val andY: (double) y_val
{
   //Concisely written class method to automatically allocate and 
   //perform specific initialization.
   return [[[Point alloc] setFirstCoord:x_val] setSecondCoord:y_val]; 
}

+ (Point *) newWithR: (double) r_val andTheta: (double) theta_val
{
   //Instead of performing the same as the above, we can underhandedly
   //use the same result of the previous method
   return [Point newWithX:r_val andY:theta_val];
}

@end

int
main(void)
{
   //Constructs two points, p and q.
   Point *p = [Point newWithX:4.0 andY:5.0];
   Point *q = [Point newWithR:1.0 andTheta:2.28];

   //...program text....
   
   //We're finished with p, say, so, free it.
   //If p allocates more memory for itself, may need to
   //override Object's free method in order to recursively
   //free p's memory. But this is not the case, so we can just
   [p free];

   //...more text...

   [q free];

   return 0;
}

Nesne Pascal

İlgili Diller: "Delphi", "Free Pascal", "Mac Pascal".

program Example;

type

  DimensionEnum =
    (
      deUnassigned,
      de2D,
      de3D,
      de4D
    );

  PointClass = class
  private
    Dimension: DimensionEnum;

  public
    X: Integer;
    Y: Integer;
    Z: Integer;
    T: Integer;

  public
    (* prototype of constructors *)

    constructor Create();
    constructor Create(AX, AY: Integer);
    constructor Create(AX, AY, AZ: Integer);
    constructor Create(AX, AY, AZ, ATime: Integer);
    constructor CreateCopy(APoint: PointClass);

    (* prototype of destructors *)

    destructor Destroy;
  end;

constructor PointClass.Create();
begin
  // implementation of a generic, non argument constructor
  Self.Dimension := deUnassigned;
end;

constructor PointClass.Create(AX, AY: Integer);
begin
  // implementation of a, 2 argument constructor
  Self.X := AX;
  Y := AY;

  Self.Dimension := de2D;
end;

constructor PointClass.Create(AX, AY, AZ: Integer);
begin
  // implementation of a, 3 argument constructor
  Self.X := AX;
  Y := AY;
  Self.X := AZ;

  Self.Dimension := de3D;
end;

constructor PointClass.Create(AX, AY, AZ, ATime: Integer);
begin
  // implementation of a, 4 argument constructor
  Self.X := AX;
  Y := AY;
  Self.X := AZ;
  T := ATime;

  Self.Dimension := de4D;
end;

constructor PointClass.CreateCopy(APoint: PointClass);
begin
  // implementation of a, "copy" constructor
  APoint.X := AX;
  APoint.Y := AY;
  APoint.X := AZ;
  APoint.T := ATime;

  Self.Dimension := de4D;
end;

destructor PointClass.PointClass.Destroy;
begin
  // implementation of a generic, non argument destructor
  Self.Dimension := deUnAssigned;
end;

var
  (* variable for static allocation *)
  S:  PointClass;
  (* variable for dynamic allocation *)
  D: ^PointClass;

begin (* of program *)
  (* object lifeline with static allocation *)
  S.Create(5, 7);

  (* do something with "S" *)

  S.Destroy; 

  (* object lifeline with dynamic allocation *)
  D = new PointClass, Create(5, 7);

  (* do something with "D" *)

  dispose D, Destroy;
end.  (* of program *)

piton

class Socket:
    def __init__(self, remote_host: str) -> None:
        # connect to remote host

    def send(self):
        # Send data

    def recv(self):
        # Receive data
        
    def close(self):
        # close the socket
        
    def __del__(self):
        # __del__ magic function called when the object's reference count equals zero
        self.close()

def f():
    socket = Socket("example.com")
    socket.send("test")
    return socket.recv()

Soket, "f" işlevi çalıştıktan ve geri döndükten sonra bir sonraki çöp toplama turunda kapatılacaktır, çünkü ona tüm referanslar kaybolmuştur.

Ayrıca bakınız

Notlar

Referanslar