Este timpul pentru un alt tip de depanare rapidă. Vom continua să ne concentrăm asupra unor erori specifice (și comune) care au tendința de a împiedica ActionScripters mai puțin experimentați. În acest caz, vom acoperi eroarea # 1063, eroarea de asimetrie a numărului de argument.
Mai întâi, să creăm o situație în care apare eroarea. Deschideți un nou document Flash (presupunând că urmăriți împreună cu Flash Pro CS3 +, altfel acest exemplu este ușor de adaptat la un proiect Flex). Deschideți Editorul Script și introduceți următorul cod:
importul flash.events.MouseEvent; funcția onClick (): void trace ("faceți clic pe."); stage.addEventListener (MouseEvent.CLICK, onClick);
Probabil că puteți găsi problema deja; dacă ați cheltuit ceva timp scriind ActionScript 3, ați fi găsit că ați scris manageri de evenimente. Dacă nu, nu vă simțiți rău - vom trece peste tot în curând.
Dacă rulați fișierul Flash ca atare și apoi faceți clic pe scenă, veți produce următorul mesaj de eroare de execuție:
ArgumentError: Eroare # 1063: Neconcordanța numărului de argumente pe Untitled_fla :: MainTimeline / onClick (). Așteptat 0, am 1.
Și nu ajungem niciodată la următoarea afirmație ar trebui să au rulat după ce au dat clic.
Deci ce se întâmplă? În acest caz, verbiajul Adobe pentru eroare nu este de fapt așa de rău și dacă te-ai obișnuit să analizezi un mesaj de eroare în timp de execuție, sensul său ar putea fi destul de clar. Dar nu toată lumea este la fel de inteligentă ca tine, deci iată defalcarea pentru toți ceilalți.
ArgumentError -- Aceasta este o informație oarecum inconsecventă, dar arată specificul Eroare
clasa care a fost aruncată. Avem ceva care nu este la fel de general ca simplu Eroare
, și am introdus o categorizare specifică a erorilor asociate cu argumentele (la funcții și metode).
Eroare # 1063 -- Aici dăm doar numărul oficial de eroare, ca toate erorile bune de execuție. Puteți utiliza acest cod pentru ao găsi mai ușor în documentația de eroare de execuție Adobe.
Argumentul numarare nepotrivire? -- În mai multe condiții proletariene, au existat un număr greșit de argumente trimise la o funcție. Ce funcție? este?
? pe Untitled_fla :: MainTimeline / onClick (). -- Aceasta identifică pur și simplu funcția care a primit numărul greșit de argumente.
Așteptat 0, am 1. -- În această descriere de eroare primim câteva informații suplimentare. Aceasta detaliază neconcordanța numărului. Această expresie se va schimba în funcție de natura erorii specifice, dar în cazul nostru se spune că funcția a fost scrisă fără argumente în semnătură, dar oricum a fost trimis un singur argument.
Flash îi place rațele în rând. Deci, constată această discrepanță și decide să arunce o acces de furie eroare, pentru că mai degrabă dvs. (dezvoltatorul) ați dat seama ce a mers prost decât că ați ignorat pur și simplu problema. Acest lucru este bun, pentru că dacă neconcordanța numărului a mers în altă direcție (așteptat 1, am primit 0), atunci ne-am fi blocat fără un argument pentru un parametru necesar și funcția ar face câine știe ce.
Natura erorii ar trebui să fie clară în acest moment, dar s-ar putea să te întrebi de ce a apărut deloc. De unde a venit acest argument inutil?
Argumentul nu este chiar inutil. Este de așteptat, de fapt, de când ne-am cuplat funcția de a fi un ascultător al evenimentului. Sistemul de evenimente din Flash are noțiunea de eveniment obiect care încapsulează aspecte ale evenimentului care a avut loc. Acest obiect este transmis funcției ascultătorului drept singurul argument. Deci, noi așteptat 0 pentru că am scris funcția noastră fără parametri, dar noi am 1 deoarece dispecerul evenimentului a trimis un obiect de eveniment.
Acum s-ar putea să te întrebi de ce compilatorul nu a prins această eroare. Este adevărat: dacă ați scris acest lucru:
funcția sayClick (): void trace ("faceți clic pe."); sayClick (42);
Apoi SWF nu se va compila chiar, pentru că veți obține această eroare:
1137: Număr incorect de argumente. Nu se aștepta mai mult de 0.
Diferența este că în ultimul exemplu, avem un cod real care numește funcția cu un număr greșit de argumente. Asta înseamnă că am scris linia care sună în mod incorect. Compilatorul poate să privească linia care definește funcția și linia care apelează funcția și să o compare cu discrepanțele și să sune alarma atunci când acestea apar.
Cu toate acestea, în exemplul original, nu există nicio linie de cod scrise care să numească funcția în mod literal. În schimb, funcția este numită prin referință. Când adăugăm ascultătorul evenimentului, trecem în funcție, iar la acel moment este o variabilă, nu un apel de funcție. Această referință este stocată de dispecerul evenimentului și apoi executată dinamic la producerea evenimentului (aceasta este o prezentare reală la nivel înalt a modului în care funcționează sistemul de evenimente, dar nu avem timp să mergem mai adânc). Deci, linia de cod care în cele din urmă numește funcția care cauzează erori este o linie destul de generică de cod care folosește indirecția pentru a face treaba și, prin urmare, ceva mult mai greu pentru compilator să prindă.
(În opinia mea, Adobe ar putea cel puțin să înregistreze addEventListener
line la timpul de compilare și căutați referința funcției după nume. Dacă găsește o potrivire, ar putea verifica semnătura funcției pentru un argument corespunzător evenimentului și poate produce erori în consecință. Încă nu se putea face într-un mod sigur, dar ar putea merge mult pentru a prinde aceste erori înainte de a rula efectiv SWF.
Punctul principal, totuși, este că această eroare de execuție are un omolog de compilare, dar că eroarea de execuție apare atunci când funcția este apelată prin referință și nu direct prin nume.
Ploaia intră când numim funcția prin referință și avem o discrepanță în numărul de argumente. În general, avem două opțiuni: putem modifica apelul sau putem modifica argumentele funcției. În acest exemplu, nu putem modifica apelul, așa cum se întâmplă în interiorul acestuia EventDispatcher
, cod la care nu avem acces. Asta ne lasă să modificăm argumentele.
Aceasta, din nou, are două opțiuni. În primul rând, putem adăuga pur și simplu argumentul. Aceasta ordonează numărul de argumente și de aici, totul va fi copacetic. Nu este nevoie să folosim argumentul, trebuie doar să avem funcția? când este numit.
funcția onClick (e: MouseEvent): void
A doua opțiune este, din nou, să adăugați argumentul (nu mă înspăimânt). Cu toate acestea, dacă ați scris inițial funcția ca o funcție obișnuită și nu un ascultător de evenimente și o sunați din altă parte a codului dvs. fără argumente, puteți aprecia această variație. Efectuați argumentul opțional și impliciți-l la nul
:
funcția onClick (e: MouseEvent = null): void
Acest lucru va funcționa bine cu sistemul de evenimente: acesta primește un obiect de eveniment și îl poate prinde. De asemenea, funcționează bine cu codul existent; dacă nu este trimis niciun argument, parametrul implicit este utilizat și funcția continuă.
Rețineți că această eroare nu se limitează la ascultătorii evenimentului, deși acesta este probabil cel mai comun context în care îl veți experimenta. În cele din urmă, utilizarea funcțiilor stocate în variabile, spre deosebire de numele numit, duce la eroare. Acesta este modul în care sistemul de evenimente funcționează. Putem redimensiona exemplul original pentru a produce mai mult sau mai puțin aceeași eroare, numai fără clic:
funcția sayMyName (nume: String): void trace ("Hello", + nume); var funcRef: Funcție = sayMyName; funcRef ();
Din nou, depășim eroarea de compilator deoarece avem un strat de indirecție între definiția funcției și apelul funcției. Astfel, obținem eroarea de timp de execuție (așteptat 1, am primit 0).
Nu e întotdeauna această tăietură și uscată. Dacă utilizați callbacks în codul dvs., s-ar putea să cădeați pradă erorii 1063. Retragerile de apel sunt un fel de ascultători de evenimente, dar nu există un mecanism formal, construit pentru a le implementa. Ele sunt, în principiu, doar funcții pe care le transmiteți prin referință, care sunt stocate (fie temporar, fie pe termen lung) printr-un alt proces, care apoi apelează funcția de apel invers la momentul potrivit.
Motoarele tweening le implementează în mod obișnuit. Unii se îndreaptă spre un sistem mai formal, bazat pe evenimente, dar TweenLite, de exemplu, utilizează apeluri telefonice pentru a primi notificări despre progresul tween. Această linie:
TweenLite.to (uneleClip, 1, onComplete: tweenFinished, onCompleteParams: [42, "răspuns"]);
? ar numi o funcție numită tweenFinished
la sfârșitul versiunii tween, trecând în funcție de doi parametri. Această tehnică este în cele din urmă mai flexibilă decât evenimentele, deoarece nu vă limitați doar la obiectul unic de eveniment ca parametru. Dar se pretează la vulnerabilități similare la eroarea 1063 datorită naturii funcțiilor de trecere prin referință.
Acest lucru împachetează un alt sfat rapid de depanare. Vă mulțumim pentru lectură și sper că ați învățat ceva de-a lungul drumului!