Динамикалық диспетчер - Dynamic dispatch

Жылы есептеу техникасы, динамикалық диспетчер а-ның қайсысын жүзеге асыратынын таңдау процесі полиморфты операция (әдіс немесе функция) қоңырау шалу үшін жұмыс уақыты. Ол әдетте жұмыс істейді және сипаттамалары болып саналады, объектіге бағытталған бағдарламалау (OOP) тілдері мен жүйелері.[1]

Объектіге бағытталған жүйелер проблеманы атымен аталған әрекеттерді жүзеге асыратын өзара әрекеттесетін объектілер жиынтығы ретінде модельдейді. Полиморфизм - бұл бір-бірімен алмастырылатын объектілердің әрқайсысы бірдей атпен жасалатын, бірақ мінез-құлқымен ерекшеленетін әрекетті көрсететін құбылыс. Мысал ретінде, а Файл объект және а Дерекқор объектінің екеуі де бар StoreRecord кадрлық жазбаны сақтау үшін жазуға болатын әдіс. Олардың орындалуы әр түрлі. Бағдарлама а-ға сілтеме жасайды, ол а болуы мүмкін Файл объект немесе а Дерекқор объект. Оның қайсысы жұмыс уақыты параметрімен анықталған болуы мүмкін және осы кезеңде бағдарлама қайсысын білмеуі немесе ойламауы мүмкін. Бағдарлама қоңырау шалғанда StoreRecord объект бойынша, қандай мінез-құлық қабылданатынын таңдау керек. Егер біреу OOP туралы ойласа хабарламалар жіберу нысандарға, онда бұл мысалда бағдарлама а жібереді StoreRecord белгісіз типтегі объектіге хабарлама жіберіп, оны қажетті объектіге жіберу үшін оны жұмыс уақытының қолдау жүйесіне қалдырыңыз. Нысан қандай мінез-құлықты іске асырса да іске асырады.[2]

Динамикалық диспетчерге қарама-қайшы келеді статикалық диспетчер, онда полиморфты операцияны орындау таңдалады жинақтау уақыты. Динамикалық диспетчердің мақсаты - параметрдің (немесе бірнеше параметрдің) жұмыс уақыты типі белгілі болғанға дейін тиісті іске асыруды таңдауды кейінге қалдыру.

Динамикалық диспетчердің айырмашылығы кеш байланыстыру (динамикалық байланыстыру деп те аталады). Атауы міндетті атауды амалмен байланыстырады. Полиморфты операцияның бірнеше орындалуы бар, олардың барлығы бірдей атпен байланысты. Іліністер компиляция кезінде немесе (кеш байланыстырумен) жұмыс уақытында жасалуы мүмкін. Динамикалық диспетчерлеу кезінде операцияның нақты бір орындалуы жұмыс уақытында таңдалады. Динамикалық диспетчер кеш байланыстыруды білдірмейді, ал кеш байланыстыру динамикалық диспетчерді білдіреді, өйткені кеш байланыстырылған операцияның орындалуы жұмыс уақытына дейін белгісіз.[дәйексөз қажет ]

Бір және бірнеше рет жіберу

Қандай әдісті шақыру керектігін таңдау бір объектіге немесе объектілер тіркесіміне негізделуі мүмкін. Біріншісі деп аталады бір рет жіберу сияқты жалпы нысандарға бағытталған тілдермен тікелей қолдау көрсетіледі Smalltalk, C ++, Java, Мақсат-С, Свифт, JavaScript, және Python. Осы және ұқсас тілдерде әдісті шақыруға болады бөлу ұқсас синтаксиспен

дивиденд.бөлу(бөлгіш)  # дивиденд / бөлгіш

мұнда параметрлер міндетті емес. Бұл туралы хабарлама жіберу деп ойлайды бөлу параметрімен бөлгіш дейін дивиденд. Іске асыру тек негізінде таңдалады дивидендтүрі (мүмкін рационалды, өзгермелі нүкте, матрица ) типін немесе мәнін ескермей бөлгіш.

Керісінше, кейбір тілдер операндтардың тіркесіміне негізделген әдістерді немесе функцияларды жібереді; бөлу жағдайында дивиденд және бөлгіш бірге қандайын анықтаңыз бөлу операция жасалады. Бұл белгілі бірнеше рет жіберу. Бірнеше диспетчерді қолдайтын тілдердің мысалдары Жалпы Лисп, Дилан, және Джулия.

Динамикалық диспетчерлік механизмдер

Тіл әртүрлі динамикалық диспетчерлік механизмдермен жүзеге асырылуы мүмкін. Тіл ұсынатын динамикалық диспетчер механизмінің таңдаулары белгілі бір тілде қол жетімді немесе табиғи болып табылатын бағдарламалау парадигмаларын едәуір дәрежеде өзгертеді.

Әдетте типтелген тілде диспетчерлік механизм аргументтер типіне байланысты орындалады (көбінесе хабарлама қабылдағыш типіне негізделген). Теру жүйесі әлсіз немесе мүлдем жоқ тілдер диспетчерлік кестені әр объект үшін объектілік мәліметтер бөлігі ретінде жиі алып жүреді. Бұл мүмкіндік береді даналық тәртіп өйткені әрбір дана берілген хабарламаны бөлек әдіспен салыстыра алады.

Кейбір тілдер гибридті тәсілді ұсынады.

Динамикалық диспетчер әрқашан үстеме ақыға ие болады, сондықтан кейбір тілдер белгілі бір әдістерге статикалық диспетчерді ұсынады.

C ++ енгізу

C ++ ерте байланыстыруды қолданады және динамикалық және статикалық диспетчерді ұсынады. Жіберудің әдепкі түрі статикалық болып табылады. Динамикалық диспетчер алу үшін бағдарламашы әдісті келесідей жариялауы керек виртуалды.

C ++ компиляторлары әдетте а деп аталатын мәліметтер құрылымымен динамикалық диспетчерлеуді жүзеге асырады виртуалды функциялар кестесі (vtable), берілген сынып үшін іске асыруға арналған картаны мүше функциясының көрсеткіштерінің жиынтығы ретінде анықтайды. (Бұл тек іске асырудың егжей-тегжейі; C ++ спецификациясында кестелер туралы айтылмайды.) Осы типтегі даналар сілтегішті осы кестеге олардың даналық деректерінің бөлігі ретінде сақтайды. Бұл қашан қиын бірнеше мұрагерлік қолданылады. C ++ кеш байланыстыруды қолдамайтындықтан, C ++ нысанындағы виртуалды кестені жұмыс уақытында өзгерту мүмкін емес, бұл диспетчерлік мақсаттың ықтимал жиынтығын компиляция кезінде таңдалған ақырлы жиынтықпен шектейді.

Түрдің шамадан тыс жүктелуі C ++ тілінде динамикалық диспетчерді тудырмайды, өйткені тіл хабарлама параметрлерінің типтерін ресми хабарлама атауының бөлігі ретінде қарастырады. Бұл бағдарламашының көретін хабар атауы байланыстыру үшін қолданылатын ресми атау емес екенін білдіреді.

Go және Rust-ті енгізу

Жылы Барыңыз және Тот, ерте байланыстырудың неғұрлым жан-жақты вариациясы қолданылады. Vtable көрсеткіштері объект сілтемелерімен бірге «майлы көрсеткіштер» (Go-да «интерфейстер» немесе Rust-та «нысандар объектілері») ретінде жүзеге асырылады.

Бұл қолдау көрсетілетін интерфейстерді негізгі деректер құрылымынан ажыратады. Әрбір жинақталған кітапхана типті дұрыс қолдану үшін қолдау көрсетілетін интерфейстің барлық ауқымын білуі керек, тек оларға қажет нақты кесте орналасуын білуі керек. Код әр түрлі интерфейстерді айналып өтіп, мәліметтердің бір бөлігіне әртүрлі функцияларға ауыса алады. Бұл әмбебаптық әр объект сілтемесімен бірге қосымша мәліметтер есебінен жүреді, егер мұндай сілтемелердің көпшілігі үнемі сақталса, мәселе туындайды.

Smalltalk іске асыру

Smalltalk типке негізделген хабарлама диспетчерін қолданады. Әр дананың жеке типі бар, оның анықтамасында әдістер бар. Дана хабарлама алған кезде диспетчер хабарлама-әдіс картасында типке сәйкес әдісті іздейді, содан кейін әдісті шақырады.

Бір типте базалық типтер тізбегі болуы мүмкін болғандықтан, бұл іздеу қымбатқа түседі. Smalltalk механизмін аңғалдықпен жүзеге асыру С ++ -ге қарағанда айтарлықтай жоғары үстеме ақыға ие болып көрінуі мүмкін және бұл қосымша хабарлама объекті алған әрбір хабарлама үшін қажет болады.

Нақты Smalltalk бағдарламаларында көбінесе белгілі әдістеме қолданылады ішкі кэштеу[3] бұл әдіс жіберуді өте жылдам етеді. Кірістірілген кэштеу негізінен шақыру сайтының алдыңғы тағайындалған әдісінің мекен-жайы мен объектілік класын сақтайды (немесе көпжақты кэштеу үшін бірнеше жұп). Кэштелген әдіс әдіс таңдағышқа негізделген ең көп таралған мақсатты әдіспен инициализацияланады (немесе жай ғана кэш жіберуді өңдеуші). Орындау кезінде әдіс шақыру сайтына жеткенде, ол жай ғана кэштегі мекен-жайға қоңырау шалады. (Динамикалық код генераторында бұл қоңырау тікелей қоңырау болып табылады, өйткені тікелей мекен-жайы кэштің жіберілу логикасымен кері қайтарылады.) Шақырылған әдіс бойынша пролог коды кэштелген класты нақты объектілер класымен салыстырады, егер олар сәйкес келмесе , орындау әдісі сыныптағы дұрыс әдісті табу үшін кэшті жіберушіге таралады. Жылдам іске асырудың бірнеше кэш жазбалары болуы мүмкін және кэштің алғашқы жіберілуінде дұрыс әдіске сәйкес орындау үшін тек бірнеше нұсқаулар қажет. Жалпы жағдай кэштелген класты сәйкестік болады, ал орындау тек әдіс бойынша жалғасады.

Желіден тыс кэштеуді әдіс шақыру логикасында, объект сыныбы мен әдіс таңдау құралын қолдана отырып та қолдануға болады. Бір дизайнда класс пен әдіс таңдау құралы жинақталған және әдіс диспетчерлік кэш кестесінде индекс ретінде қолданылады.

Smalltalk рефлексиялық тіл болғандықтан, көптеген іске асырулар жеке объектілерді объектілерге динамикалық түрде құрылған әдіс іздеу кестелерімен мутация жасауға мүмкіндік береді. Бұл нысанға байланысты мінез-құлықты өзгертуге мүмкіндік береді. Ретінде белгілі тілдердің тұтас категориясы прототипке негізделген тілдер осыдан өсіп келеді, олардың ішіндегі ең танымал Өзіндік және JavaScript. Диспетчерлік кэштеуді мұқият жобалау прототипке негізделген тілдерге де жоғары өнімділікті жіберуге мүмкіндік береді.

Басқа динамикалық терілген тілдер, соның ішінде Python, Рубин, Мақсат-С және Groovy ұқсас тәсілдерді қолданыңыз.

Python-дағы мысал

сынып Мысық:    деф сөйлеу(өзіндік):        басып шығару(«Мияу»)сынып Ит:    деф сөйлеу(өзіндік):        басып шығару(«Вуф»)деф сөйлеу(үй жануарлары):    # Сөйлеу әдісін динамикалық түрде жібереді    # үй жануарлары мысықтар мен иттердің мысалы бола алады    үй жануарлары.сөйлеу()мысық = Мысық()сөйлеу(мысық)ит = Ит()сөйлеу(ит)

Сондай-ақ қараңыз

Әдебиеттер тізімі

  1. ^ Милтон, Скотт; Шмидт, Хайнц В. (1994). Объектілі тілдерде динамикалық диспетчерлеу (Техникалық есеп). TR-CS-94-02. Австралия ұлттық университеті. CiteSeerX  10.1.1.33.4292.
  2. ^ Дризен, Карел; Хольц, Урс; Витек, қаңтар (1995). Құбырлы процессорларға хабарлама жіберу. ECOOP. CiteSeerX  10.1.1.122.281.
  3. ^ Мюллер, Мартин (1995). Динамикалық типтегі нысанға бағытталған тілдерде хабарлама жіберу (Магистрлік диссертация). Нью-Мексико университеті. 16-17 бет. CiteSeerX  10.1.1.55.1782.

Библиография