Кіріспе
Бағдарламалауда, объектінің құрылуы мен жойылуы арасындағы уақыт. Объектіге бағытталған бағдарламалауда (ООП) объектінің өмір сүру мерзімі (немесе өмірлік циклы) – объектінің құрылуынан оның жойылуына дейінгі уақытты білдіреді. Объектінің өмір сүру мерзіміне қатысты ережелер тілдер арасында, тіпті бір тілдің әртүрлі нұсқаларында да айтарлықтай өзгеше болуы мүмкін, ал нақты объектінің өмір сүру мерзімі бағдарламаның әр рет іске қосылуында өзгеріп отыруы мүмкін. Кейбір жағдайларда объектінің өмір сүру мерзімі сол объектіні құрайтын айнымалының өмір сүру мерзімімен сәйкес келеді (статикалық және автоматты айнымалылар үшін), бірақ көбінесе объектінің өмір сүру мерзімі ешбір айнымалының өмір сүру мерзімімен тікелей байланысты емес. Көптеген жағдайларда – және көптеген объектіге бағытталған тілдерде, әсіресе қоқыс жинау (GC) механизмін қолданатындарда – объектілер жедел жадқа (heap) орналастырылады, ал объектінің өмір сүру мерзімі нақты айнымалының өмір сүру мерзімімен анықталмайды: айнымалының мәні объектінің өзіне емес, оған сілтемеге сәйкес келеді, ал айнымалыны жою тек сілтемені жояды, ал объектінің өзін емес.
In object oriented programming (OOP), the object lifetime (or life cycle) of an object is the time between an object's creation and its destruction. Rules for object lifetime vary significantly between languages, in some cases between implementations of a given language, and lifetime of a particular object may vary from one run of the program to another. In some cases, object lifetime coincides with variable lifetime of a variable with that object as value (both for static variables and automatic variables), but in general, object lifetime is not tied to the lifetime of any one variable. In many cases – and by default in many object oriented languages, particularly those that use garbage collection (GC) – objects are allocated on the heap, and object lifetime is not determined by the lifetime of a given variable: the value of a variable holding an object actually corresponds to a reference to the object, not the object itself, and destruction of the variable just destroys the reference, not the underlying object.
Шолу
Объектінің өмір сүру ұзақтығының негізгі идеясы қарапайым: объект құрылады, қолданылады, содан кейін жойылады. Бірақ бұл процестің егжей-тегжейлері тілдер арасында және тілдің нақты іске асырылуында айтарлықтай өзгеше болуы мүмкін, сонымен қатар жадты басқару қалай іске асырылғандығымен тығыз байланысты. Бұдан өзге, қадамдар арасында, сондай-ақ тіл деңгейіндегі және іске асыру деңгейіндегі түсініктер арасында көптеген ұсақ айырмашылықтар бар. Терминология көбінесе стандартты, бірақ нақты терминге сәйкес келетін қадамдар тілдерге қарай өте әртүрлі болуы мүмкін. Терминдер әдетте антоним жұптар түрінде келеді: біреуі объектіні құруға қатысты, екіншісі – жоюға, мысалы, инициализация/финализация немесе конструктор/деструктор. Объектіні құру/жою жұбы бастау/тоқтату деп те аталады. Жадты басқарудағы сияқты, аллокация және деаллокация немесе босату терминдері де қолданылады. Алайда, объектіні құру және жою жай ғана жадты бөлу мен босатудан әлдеқайда күрделі болуы мүмкін, ал аллокация/деаллокация тиісінше құру және жою процесінің қадамдары болып есептеледі.
Детерминизм
Негізгі айырмашылық – объектінің өмір сүру мерзімі детерминистік немесе детерминистік емес болуында. Бұл тілдерге байланысты өзгереді, ал тіл ішінде объектінің жадқа бөлінуіне байланысты да өзгереді; объектінің өмір сүру мерзімі айнымалының өмір сүру уақытынан өзгеше болуы мүмкін. Статикалық жадқа бөлінген объектілер, атап айтқанда статикалық айнымалыларда сақталатын объектілер және сынып модульдері (егер сыныптар немесе модульдер өздері объектілер болса және статикалық түрде бөлінген болса), көптеген тілдерде айқын емес детерминизмге ие: олардың өмір сүру мерзімі бағдарламаның жұмыс ілу уақытымен сәйкес келеді, бірақ құру және жою реті – қай статикалық объекті бірінші, қайсы екінші болып құрылады және т.б. – көбінесе детерминистік емес. Автоматты жадқа немесе динамикалық жадқа бөлінген объектілер үшін объектіні құру көбінесе детерминистік түрде жүзеге асырылады, яғни нақты түрде объект жасалғанда (мысалы, C++ немесе Java-да `new` арқылы) немесе жасырын түрде айнымалының өмір сүру мерзімінің басында, әсіресе автоматты айнымалының қолданыс аймағына кіргенде, мысалы, жарияланғанда. Объектілерді жою әртүрлі болады, бірақ кейбір тілдерде, атап айтқанда C++, автоматты және динамикалық объектілер детерминистік уақытта жойылады, мысалы, қолданыс аймағынан шығу, нақты жою (қолмен жадты басқару арқылы) немесе сілтеме санының нөлге желуі; ал басқа тілдерде, мысалы, C#, Java және Python, бұл объектілер детерминистік емес уақытта жойылады, қоқыс жинаушыға байланысты, және объектінің қайта жандануы жою кезінде болуы мүмкін, өмір сүру мерзімін ұзартады. Қоқыс жиналатын тілдерде объектілер, әдетте, бастапқыда автоматты айнымалыға байланысты болса да, динамикалық түрде (қаптамада) бөлінеді, примитивті мәндері бар автоматты айнымалылардан өзгеше, олар әдетте автоматты түрде бөлінеді (стекте немесе тіркелгіште). Бұл объектіні функциядан ("қашып кету") жойылмай қайтаруға мүмкіндік береді. Алайда, кейбір жағдайларда компиляторды оңтайландыру мүмкін, атап айтқанда, қашып кетуді талдау және қашып кетудің мүмкін еместігін дәлелдеу, сонда объекті стекте бөлінуі мүмкін; бұл Java-да маңызды. Бұл жағдайда объектіні жою жылдам жүреді – тіпті айнымалының өмір сүру мерзімі ішінде (оның қолданыс аймағы аяқталуына дейін), егер ол қолжетімді болмаса. Күрделі жағдай – объектілер пулын пайдалану, онда объектілер уақытынан бұрын құрылуы немесе қайта пайдаланылуы мүмкін, сондықтан көрінетін құру және жою объектінің нақты құрылуы мен жоюына сәйкес келмейді, тек құру үшін (қайта) бастау және жою үшін аяқтау. Бұл жағдайда құру да, жою да детерминистік емес болуы мүмкін.
Жаратылыс пен жойылу кезіндегі жағдайы
Маңызды бір нюанс – объектінің құрылуы немесе жойылуы кезіндегі күйі, сондай-ақ қателер туындаған немесе ерекше жағдайлар орын алған кездегі жағдайларды басқару, мысалы, егер құрылу немесе жою сәтсіз аяқталса. Қатаң айтқанда, объектінің өмір сүру мерзімі бөліну аяқталғанда басталады және босату басталғанда аяқталады. Осылайша, инициализация және финализация кезінде объект тірі болады, бірақ тұрақты күйде болмауы мүмкін – сыныптың инварианттарын қамтамасыз ету инициализацияның маңызды бөлігі болып табылады, ал инициализация аяқталғаннан бастап финализация басталғанға дейінгі кезеңде объекті тірі және тұрақты күйде болуы күтіледі. Егер құрылу немесе жою сәтсіз болса, қате туралы хабарлау (әдетте ерекшеліктерді тудыру арқылы) қиын болуы мүмкін: объекті немесе байланысты объектілер тұрақсыз күйде болуы мүмкін, ал жою жағдайында – әдетте бұл жасырын түрде жүзеге асады, демек, белгісіз ортада – қателерді өңдеу қиын болуы мүмкін. Керісінше мәселе – кіріс ерекшеліктер, шығыс ерекшеліктер емес – ерекшеліктерді өңдеу кезінде құрылу немесе жою әртүрліше болуы керек пе, жоқ па. Тағы бір нюанс – статикалық айнымалылардың құрылуы және жойылуы, олардың өмір сүру мерзімі бағдарламаның жұмыс ілу уақытына сәйкес келеді. Құрылу және жою бағдарламаның қалыпты орындалуы кезінде ме, әлде бағдарламаны орындау алдында және кейін арнайы кезеңдерде ме жүзеге асырылады және бағдарлама аяқталғанда объектілер қалай жойылады, онда бағдарлама әдеттегі немесе тұрақты күйде болмауы мүмкін. Бұл әсіресе қоқыс жиналатын тілдер үшін маңызды, себебі бағдарлама аяқталғанда көптеген пайдасыз деректер болуы мүмкін.
Сыныптарға негізделген бағдарламалау
Сыныпқа негізделген бағдарламалауда объектіні құруды инстанция (сыныптың инстанциясын жасау) деп те атайды, ал құру мен жоюды конструктор мен деструктор немесе инициализатор мен финализатор деп аталатын әдістер арқылы басқаруға болады. Құру және жою сонымен қатар құрастыру және жою деп аталады, ал бұл әдістерді шақырғанда объект құрастырылған немесе жойылған (жойылмаған) деп айтылады, тиісінше, осы әдістерді шақырғанда бастамаланған немесе аяқталған. Бұл әдістер арасындағы қарым-қатынас күрделі болуы мүмкін, ал тілде конструкторлар мен инициализаторлар (Python сияқты) немесе деструкторлар мен финализаторлар (C++/CLI сияқты) болуы мүмкін, немесе "деструктор" және "финализатор" терминдері тіл деңгейіндегі құрылымға қарсы жүзеге асырылуы мүмкін (C# пен CLI сияқты). Басты айырмашылық – конструкторлар сынып әдістері болып табылады, себебі объект (сынып инстанциясы) құрылғанға дейін қолжетімді емес, ал қалған әдістер (деструкторлар, инициализаторлар және финализаторлар) – инстанциялық әдістер, өйткені объект құрылған. Сонымен қатар, конструкторлар мен инициализаторлар аргументтерді қабылдауы мүмкін, ал деструкторлар мен финализаторлар көбінесе қабылдамайды, себебі олар әдетте жасырын шақырылады. Көп қолданыста конструктор – объектіні құру үшін пайдаланушы кодын тікелей шақыратын әдіс, ал "деструктор" – детерминистік өмір сүру мерзімі бар тілдерде объект жойылғанда шақырылатын (көбінесе жасырын, бірақ кейде ашық) кіші бағдарлама, мұндағы үлгі – C++, ал "финализатор" – детерминистік емес өмір сүру мерзімі бар тілдерде объект жойылғанда қоқыс жинаушы жасырын шақыратын кіші бағдарлама, мұндағы үлгі – Java. Аяқтау кезіндегі қадамдар жадты басқару тәсіліне байланысты айтарлықтай өзгереді: жадты қолмен басқаруда (C++ немесе қолмен сілтемелерді санау сияқты) сілтемелерді бағдарламашы тікелей жоюы керек (сығармаларды тазалау, сілтемелерді санауды азайту); автоматты сілтемелерді санауда бұл да аяқталу кезінде болады, бірақ автоматтандырылады (Python-да, бағдарламашы көрсеткен финализаторлар шақырылғаннан кейін); ал іздеу арқылы қоқыс жинауда бұл қажет емес. Осылайша, автоматты сілтеме санауда бағдарламашы көрсеткен финализаторлар көбінесе қысқа немесе жоқ, бірақ маңызды жұмыс орындалуы мүмкін, ал іздеу арқылы қоқыс жинауда аяқтау көбінесе қажет емес.
Ресурстарды басқару
Объектілердің өмір сүру мерзімі анықталған тілдерде, объектінің өмір сүру мерзімін ресурстарды басқару үшін пайдалануға болады: бұл Ресурстарды алу – бастамалау (RAII) идиомасы деп аталады: ресурстар бастамалау кезінде иеленеді және жою кезінде босатылады. Объектілердің өмір сүру мерзімі анықталмаған тілдерде, әсіресе қоқыс жинау болған жағдайда, жадты басқару әдетте басқа ресурстарды басқарудан бөлек қарастырылады.
Құру әдістері
Заттарды жасау тәсілі тілдерге қарай әртүрлі болады. Кейбір сыныпқа негізделген тілдерде объектінің күйін тексеруге жауапты арнайы әдіс – конструктор болып табылады. Қалыпты әдістер сияқты, конструкторларды да жүктеуге болады, осылайша әртүрлі атрибуттармен объектіні жасауға мүмкіндік туады. Сонымен қатар, конструктор – өзгертілмейтін объектілердің күйін орнатуға арналған жалғыз орын. Көшірме конструктор – конструктор класымен бірдей типтегі қолданыстағы объектіні (бір) параметр ретінде қабылдап, параметр ретінде жіберілген объектінің көшірмесін қайтаратын конструктор. Басқа бағдарламалау тілдерінде, мысалы Objective C-де, кластық әдістер бар, олар конструктор сияқты әдістерді қамтуы мүмкін, бірақ олар тек объектілерді құрумен ғана шектелмейді. C++ және Java атаулы конструкторларды ұсынбағаны үшін сынға ұшырады, себебі конструктордың атауы әрқашан кластың атауымен сәйкес болуы керек. Егер бағдарламашы бірдей аргумент түрлерімен екі конструкторды жасағысы келсе, мысалы, декартикалық немесе полярлық координаттардан нүктелік объектіні құру үшін, бұл қиындық тудыруы мүмкін, себебі екеуі де екі қозғалмалы нүктелі санмен бейнеленеді. Objective C бұл мәселені шеше алады, бағдарламашы Point класын инициализациялау әдістерімен, мысалы, +newPointWithX:andY: және +newPointWithR:andTheta: құра алады. C++ тілінде де статикалық мүшелік функцияларды пайдаланып осыған ұқсас нәрсені жасауға болады. Конструктор сонымен қатар, функционалдық тілдерде, әсіресе, белгіленген жиынның мәнін құру үшін қолданылатын функцияға сілтеме бере алады.
gg\gY:, and +newPointWithR:andTheta:. In C++, something similar can be done using static member functions. A constructor can also refer to a function which is used to create a value of a tagged union, particularly in functional languages.
Нысанның жойылуы
Әдетте, объект қолданылғаннан кейін, жадыдан алынып тасталады, оның орнын басқа бағдарламалар немесе объектілер басады. Дегенмен, егер жеткілікті жад болса немесе бағдарламаның жұмыс істеу уақыты қысқа болса, объект жойылмай, жады процестің аяқталуымен ғана босатылуы мүмкін. Кейбір жағдайларда объектіні жою жай ғана жадты босатудан тұрады, әсіресе қоқыс жинау тілдерінде немесе егер «объект» қарапайым деректер құрылымы болса. Басқа жағдайларда жадты босату алдында кейбір жұмыстар орындалады, әсіресе құрамындағы объектілерді жою (қолмен жад басқаруда) немесе объектінің басқа объектілерге жасаған сілтемелерін жою арқылы сілтемелер санын азайту. Бұл автоматты түрде немесе объектіге арнайы жою әдісі шақырылуы мүмкін. Белгілі бір өмір сүру мерзімі бар сыныптарға негізделген тілдерде, атап айтқанда C++, деструктор – сыныптың бір данасы жойылған кезде, жады босатылудан бұрын шақырылатын әдіс. C++-та деструкторлар конструкторлардан бірнеше жағынан ерекшеленеді: оларды перезагрузкалауға болмайды, аргументтері болмауы керек, сыныптың өзгермейтін қасиеттерін сақтау міндетті емес, және егер олар қателік тудырса, бағдарлама тоқтауы мүмкін. Қоқыс жинау тілдерінде объектілер жұмыс істеп тұрған кодқа қол жеткізе алмай қалғанда жойылады. Сыныпқа негізделген қоқыс жинау тілдерінде деструкторлардың орнына finalizer қолданылады, ол объект қоқыс жиналғанға дейін шақырылады. Олар қоқыс жинаудың болжамсыздығына байланысты, белгілі бір уақытта және тәртіппен жұмыс істемейді, C++ деструкторларына қарағанда сирек қолданылады және олар аз күрделі. Мұндай тілдерге Java, Python және Ruby жатады. Объектіні жою оған жасалған барлық сілтемелерді жарамсыз етеді, ал қолмен жад басқаруда қолданыстағы сілтемелер «асылып қалған» сілтемелерге айналады. Қоқыс жинауда (қоқыс жинау іздеуі және сілтемелерді санау) объектілер оларға сілтемелер болмағанда ғана жойылады, бірақ түпкілікті өңдеу объектіге жаңа сілтемелерді құруы мүмкін, ал сілтемелердің асылып қалуын болдырмау үшін объект қайта жандандырылады, осылайша сілтемелер жарамды болып қалады.