AS3 101: OOP - Tilleggs Concepts

AS3 101: OOP - Ytterligere Concepts
Del
Del
Del
Del

Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av
Dette innlegget er en del av en serie som heter AS3 101.AS3 101:. Quick Tips - Ved å bruke statiske egenskaper og MethodsEverything du kunne ønske å vite om Import Statements *

For dette mega- utgaven av vår innføring i objektorientert programmering i Actionscript 3, vil vi ta en titt på noen utestående emner, samt å sette alt sammen og organisere et enkelt prosjekt rundt flere uavhengige, men likevel samarbeidsvillig, stedene.



Hvis du har fulgt sammen med AS3 101 serien så langt, har du ikke noe problem med de generelle teknikker involvert i denne opplæringen. Du får til å fokusere på hvordan de ulike elementene i hele Flash movie samhandle med hverandre og lære det grunnleggende for å bygge objektorienterte applikasjoner. Hvis du synes dette er litt over hodet, vil jeg råde deg til å gjøre retrett og friske opp de andre emner som omfattes av denne serien, nemlig de som involverer arbeider med XML, laste inn eksterne bilder, og de to første delene av denne OOP serien.


Trinn 1: Velkommen tilbake

Jeg kommer til å begynne denne opplæringen ved å snakke om om noen begreper som ikke gjør det i de tidligere OOP tutorials. Ideen om statiske medlemmer, pakker, import, kildestier, og sammensetning er alle kommer til å være nødvendig for både bildevisningen prosjektet samt din generelle pågåObjektOrientert Programmerer livsstil. Som med de fleste av mine AS3 101 tutorials, vil vi fokusere i stor grad på begrepene og teorien først, og deretter bruke dem på en mer praktisk måte senere


Trinn 2:. Static Cling

Alle de egenskaper og metoder som vi har skrevet så langt er kjent som instans egenskaper
(eller instansmetoder
, som passer). Hva betyr det? At egenskapene og metodene hører til forekomsten. Husk hvordan vi sagt at alle hus bygget fra samme blåkopi har en inngangsdør, men at egenskapene til døren kan være unik på en per-house basis? Ja, det var lenge siden, vei opp igjen i begynnelsen av første OOP opplæringen, men det er det en forekomst egenskapen er. Hver forekomst kan ha sin egen, unike verdien som er lagret i den variabelen. Det er mulig å gi én Button101 eksempel en merkelappen "Abracadabra" og et annet tilfelle en merkelappen "Hocus Pocus". Fordi hvert objekt har sin egen eiendom, har hver eksempel sin egen verdi som er lagret i den.

Men hva hvis du bare trenger et sted å lagre en verdi, en verdi som ikke trenger å endre selvstendig med hver objekt som er instansiert? Hva om Button101 hadde et hjørne radius eiendom som du ønsket å holde konsekvent på tvers av alle knappe tilfeller, slik at alle knapper hadde en konsistent utseende?

Hvis det er tilfelle, så hvorfor ikke alle tilfelle trenger sin egen kopi av samme verdi?

Det gjør det ikke. Hvis vi er sikre på at alle
tilfeller vil være i stand til å dele den samme verdi, så vi kan ha alle tilfeller faktisk har samme eiendom
. Vi gjør dette ved å erklære eiendommen som statisk. Det betyr at eiendommen (eller metode, hvis du skulle gjøre det samme til en metode) ikke tilhører forekomsten, men til klassen. Dette er som å si på blåkopi at alle hus skal ha et rødmalt tredør

Hva dette ser ut i praksis er dette:
privat Static Var cornerRadius. Number = 5;

All vi er å legge den statiske nøkkelordet. Det gjør den til en klasse eiendom
(eller, igjen, en klassemetode
). Disse kalles også statiske egenskaper
(eller ... ja, du skjønner poenget).

Legg merke til at, som overstyring søkeord, rekkefølgen mellom statisk og offentlig /privat /intern /beskyttet er ubetydelig. Igjen, skjønt, er det lurt å velge en standard og feste med det.

Hvis vi gjør dette (erklære eiendommen som statisk, ikke velge en standard), deretter alle forekomster vil ha samme verdi for cornerRadius. Dette er ikke en kopi av verdien; dette er faktisk en referanse til samme verdi i alle tilfeller.

Hvorfor gjøre dette? Vel, for en, det er steder hvor det bare er fornuftig. I scenario skissert i dette trinnet, er det fornuftig, fordi vi aldri har en variasjon i det aktuelle verdi. For en annen, kan erklære eiendommer eller metoder som statisk redusere minnebruken. Siden egenskapen peker til en enkelt verdi i minnet, og ikke spesielle forekomster av tilsvar-navngitte verdier, er det en mindre effekt på hukommelse. Selvfølgelig, i vår enkle eksempel lage et enkelt tall variabel i stedet for to er knapt verdt å vurdere, men i tilfeller der gjenstander er opprettet flere ganger i løpet og verdien som finnes i en eiendom er en betydelig datastruktur, så statiske egenskaper kan gi en menings sparing.

Hold et øye for en tangential diskusjon om når du skal bruke statiske metoder og egenskaper i nær fremtid.


For en mer inngående titt på når du skal bruke statiske metoder og egenskaper, se opp for en snart-å-være-publisert Quick Tips om Activetuts +


Trinn 3:. Pakker

En annen left er oppfatningen av pakker
. Vi har vært tankeløst uvitende om pakker til nå, men jeg tror du er klar til å håndtere det. Pakker er bare en måte å organisere koden din intro gruppe og undergrupper. Og det har mye å gjøre med den pakken søkeord som starter hver klasse fil.

Teknisk sett har vi fått hjelp pakker alt sammen. Det er umulig å ikke; at pakken søkeord definerer pakken som klassen tilhører. Vi har imidlertid vært å bruke det som kalles toppnivå pakken
. Når du skriver dette:
pakken {//Klasse koden her ...}

Du plassere din klasse i øverste nivå pakke

Av ulike grunner, men du vil kanskje. å begynne å sette dine class filer i mapper. Organisasjonen er trolig den vanligste årsaken; du ønsker å holde ulike aspekter av et prosjekt gruppert sammen og adskilt fra hverandre, etter behov. Du kan også ønske å gjenbruke en klasse navn. Hvis du kunne holde hoved klasse av én SWF i en egen mappe fra hovedklassen av en annen SWF, så du kan bruke navnet to ganger.

Pakker er akkurat slik klassene er organisert i mapper. Det er en to-trinns prosess: først må du opprette filen i en mappe struktur som gjenspeiler den organisasjonen du ønsker. Så du speile mappestrukturen etter pakken søkeord i klassen filen


Trinn 4:. Opprett et eksempel Package

Vi vil opprette en prøvepakke akkurat nå, for å illustrere hvordan dette gjøres . Vi vil faktisk ettermontere forrige tutorial prosjekt å bruke pakker. Hvis du ikke har disse filene hendig, kan en kopi av det som finnes i nedlastingspakken som "button_tutorial."

I filsystemet, opprette en mappe for å huse hele prosjektet.
< p> Kopier Flash filen til denne mappen

Lag en serie av mapper i denne mappen. De bør følge denne strukturen:

[prosjekt mappe] /

as3101 /

sample /

ui /

Nå, i as3101 /sample /mappe, kopierer document filen. Kopier Button101 klasse til as3101 /ui /mappe

Det er den første delen.; vi har fått en organisatorisk ordning på vår filsystem. Nå trenger vi å redigere disse to filer, slik at pakken kamper denne mappestrukturen

Åpne opp document, og redigere den første linjen til å lese.
Pakke as3101.sample {

På samme måte åpner opp Button101 og gjøre den første linjen lese:
pakke as3101.ui {

I andre ord, vi redigerte filene slik at litt mellom pakke og åpne klammeparentes reflekterer mappestrukturen som fører til klassefilen, relative til Flash-fil. Vi bruker prikker å skille mappeelementer, skjønt, ikke skråstreker eller omvendt skråstrek. Legg merke til at klassen navnet i seg selv er ikke inkludert; pakken er bare de omslutter mapper. Klassenavnet er fortsatt oppført etter klassen nøkkelordet.

Som en organisatorisk teknikk, åpner dette opp mange flere muligheter for å strukturere dine prosjekter. Som du skriver flere og flere klasser, vil du ønsker å gruppere beslektede klasser sammen og lage hierarkier av grupperinger. Pakker vil la deg gjøre nettopp det

Men vi er ikke ferdige her.; hvis du prøver å kjøre prosjektet akkurat nå får du ingenting; fordi vi har flyttet document, kan Flash-filen ikke finne det lenger


Trinn 5:. fullstendige klassenavn

En subtil punkt som er verdt å huske på er at som snart du bruker en pakke, din klasse navn fikk mer kompleks. Nå, for alle praktiske formål, våre to klasser er fortsatt kalles "document" og "Button101." Når du diskutere dem med andre gruppemedlemmer, kan du referere til dem av disse navnene, og selv i koden kan du fortsatt bruke disse navnene. Imidlertid teknisk sett, blir bruken av en pakke klassen navn i en lengre navn. Navnet blir pakken + "." + Klassenavnet. Det vil si, vår document er virkelig as3101.sample.DocumentClass, og Button101 er virkelig as3101.ui.Button101.

Dette er kjent som fullstendige klassenavnet
, og det vil spille en viktig rolle i å organisere våre klassefilene

Du kan også se det i dette skjemaet. as3101.ui :: Button101. Dette betyr egentlig ikke noe forskjellig fra all-dot versjon. Bare vet hvordan å lese den (du ser dette som oftest når runtime error oppstår, beskriver feilen klassene hvor feilen oppstod).

Så, hvorfor gjør vårt Flash dokumentet nå ikke gjør noe? Fordi, i dokumentegenskaper, er dokument Class satt til document. Men vår klasse er egentlig heter as3101.sample.DocumentClass. Normalt denne typen mis-navne forårsaker en kompilator feil, men i denne situasjonen Flash prøver å være nyttig. Den vet å se etter en klasse kalt document å være Flash-filen dokument klasse. Men det kan ikke finne den (det eksakte klassenavnet finnes ikke lenger siden vi har flyttet klassen til en pakke). Så, Flash skaper stille et dokument klasse, kalt document for oss. Når det skjer, gjør denne klassen ingenting bortsett forlenge MovieClip og bli kalt document. Derfor, hvis vi treffer "Test Movie", vi får ingenting; . en tom SWF, reflekterende av tomt dokument klasse opprettet for oss

Før vi rette opp dette, først bevise dette ved å åpne opp de publiserer innstillingene (Fil > Publish Settings ...) for dokumentet. Klikk på "Settings ..." knappen ved siden av "Script: Actionscript 3.0" kontroll. I vinduet som vises, klikker du på haken knappen ved siden av "Document klassen:" input:

Dette vil resultere i følgende feilmelding:

Dette er Flash måte å si det samme Jeg bare fortalte deg. Bare Flash vil ikke fortelle deg at med mindre du tar noen form for handling som vi nettopp gjorde.

For å sette ting riktig, endre verdien av at Document klassen feltet til as3101.sample.DocumentClass. Når du trykker på Return, ingenting skulle skje (det andre alternativet er å få en lignende advarsel). Når du klikker på blyantikonet, bør du se klasse åpne opp. Disse både middel vi har vellykket re-tilknyttet vår Flash-fil til sin nylig omdøpt dokument klasse.

Men hvis du tester nå, ting fortsatt ikke fungerer. På den lyse siden, vil du i det minste få noen feil som sier hvorfor ting ikke fungerer.

I kraft, vi opplever det samme problemet med Button101 klasse som vi var med document


Trinn 6: Importen

Når du begynner å sette klasser i pakker, du plutselig må forholde seg til å fortelle Flash hvor du finner dem. Vær på vakt mot problemet avdekket i det siste trinnet, men heldigvis overalt ellers saken for å fortelle Flash hvor du finner klasser er en enkel linje med kode. Dette er import uttalelse.

Du har allerede brukt dem, og kan sannsynligvis allerede gjette hvorfor de er der. Vi har skrevet ganske mange import flash.display.Sprite; . slags linjer i de to siste tutorials, men nå får vi til å skrive dem for våre egne klasser

Feilen produsert på slutten av siste trinn sa noe om en type ikke blir funnet: Button101. Det kan være litt forvirrende (og riktignok, Adobes kompilatorfeil pleier å være formulert i en mindre enn nyttig måte). Det betyr bare at vi har brukt noe som kalles Button101 men aldri definert hva som er. Vi bruker en klasse, men vi bruker ikke som fullt kvalifisert navn for å peke Flash i riktig retning

Du kan anta at alt du trenger å gjøre er noe sånt som dette:.
Div knappen: as3101.ui.Button101 = new as3101.ui.Button101 ();

Det er ikke det at det er noe galt med å bruke det fullstendige navnet, men det løser ikke problemet på hånden. For å la Flash vite hvor dette nylig flyttet Button101 klassen er, må vi import
det.

importlinjer må gå før klassen erklæringen. At det, etter at pakken åpnes, men før klassen åpnes. Liker du dette:
pakken as3101.sample {//Imports gå her. public class document strekker MovieClip {//...

De kan være i den rekkefølgen du vil, men de trenger å bli gruppert i dette området. De fleste utviklere ta seg tid til å alfabetisere sine import uttalelser (faktisk gjør dette for deg Flash Builder)

Nå, for å løse vår nåværende problem, vi bare importere Button101 klassen.
Pakke as3101.sample {import as3101.ui.Button101; //Andre import ... public class document strekker MovieClip {//...

Merk at når en klasse har blitt importert bruker sin fullstendige navnet, er den tilgjengelig for klassen ved det er kort navn. Så, linjene som leser Var knappen: Button101 = new Button101 (); trenger ikke endret. Det er ingenting galt, per se, med hjelp av fullt kvalifisert navn på dette punktet. Men importen tillater oss å bruke den korte navn, noe som betyr at vi har færre tegn fylle opp koden, som er en god ting.

Test filmen nå, og med Flash klar over hvor de ulike klassene er plassert, bør du være tilbake i business

En litt ekstra oppmerksom på import. du teknisk sett ikke trenger å skrive import uttalelser for klasser som er i samme pakke som klassen gjør import. Det vil ikke skade noe å inkludere dem, skjønt, og i mitt sinn, gjør de selv dokumentere naturimport uttalelser som en verdig praksis.

De ferdige filer for eksempel (inkludert endring pakken, inkludering av import, og den oppdaterte FLA å reflektere den nye dokument klasse) er i nedlastingspakken som "button_tutorial_packages"

For å oppsummere disse punktene på import:.

Hvis klassen du ønsker å bruke, er i en annen pakke, må du bruke import uttalelse.

Dette gjør at du kan bruke "kortnavn" av klassen, men det er OK å bruke fullt kvalifisert navn hvis du må.

Hvis klassen du ønsker å bruke, er i samme pakke, er importen uttalelsen ikke nødvendig, men det er OK å bruke det hvis du vil


Trinn 7:. joker Imports

Nå bør du vite at det er to måter å importere en klasse. Den ene er den måten vi gjorde. Liste klassen med sin fullt kvalifisert navn

Men du kan velge å bruke joker
import. Det ser slik ut:.
Import as3101.ui *;

Og den gjør det du sannsynligvis forventer det. Enhver klasse innsiden av ui pakken er nå tilgjengelig for klassen gjør import av sin korte navn.

Det er et par ting å merke seg om denne teknikken.


    Du kan " t gjøre dette: import as3101 *;.. Det vil ikke få deg noe. Jokertegn bare importere klasser som er direkte barn
    pakken spesifisert. Siden Button101 og document er begge medlemmer av under pakker av as3101, ville vi oppnår ingenting ved
    som forsøk.
  1. Bruke joker ikke automatisk kompilere hver
    klasse i pakken inn SWF. Jeg gjentar:. Det gjør ikke
    Flash kompilatoren er smart nok til å kompilere bare
    de klasser som det ser blir brukt av din SWF. Du trenger ikke
    å bekymre seg unødvendig Filstørrelse øker ved å bruke wildcard.

    Å vite dette, ved hjelp av jokertegn eller ikke bør bli en personlig preferanse. Personlig har jeg bare bruke dem på Flash Player klasser (de som starter med blits. ...). I slike tilfeller bruker jeg så mange flash.net eller flash.display klasser som det er bare lettere å sørge for at de er alle tilgjengelige uten å måtte trave tilbake til import delen og legge til en ny import. Men med de klasser som jeg skriver, finner jeg det nyttig å spesifikt liste importen individuelt, som en form for dokumentasjon. Du kan se på import seksjonen og se på hvilke andre klasser denne klassen er avhengig. Valget er opp til deg, men jeg vil råde deg å finne din konvensjonen og hold deg til den.


    Jeg skal skrive en rask spiss som dykker dypere inn i import. Som vil bli utgitt før lenge, så holder øret til bakken hvis du ønsker å vite mer om de subtile detaljer om import uttalelser.


    For en dypere diskusjon om joker import holde et øye for en kommende Activetuts + Quick Tips om emnet ..


    Trinn 8: Source Paths

    Hvis vi skal snakke om å bruke pakkene til å organisere våre class filer, bør vi da utvide diskusjonen til kilde baner. En kilde bane er en katalog som Flash vil se etter klasser å kompilere. Som standard kjenner hver Flash dokument å se i Flash dokumentets egen katalog for class-filer. Dette er grunnen til at våre eksempler har jobbet så langt; våre klasser har alltid vært i samme mappe som Flash dokument (husk at vår siste venture i pakker teknisk setter klassen file
    inn i en annen mappe, men at den fullstendige klassen navn
    løser klassen til en rekke mapper pluss filen. Og rotmappen våre pakker er i samme mappe som Flash dokument).

    Nå er det en rekke grunner til hvorfor du vil ønsker å lagre klasser på annen katalog. To av de vanligste er:


      Du har gjenbrukbare verktøy klasser (muligens TweenMax, Away3D, eller noe nyttig du har skrevet). Du ønsker å bruke disse klassene
      tvers av alle prosjekter, og ikke ønsker å måtte kopiere filer fra ett prosjekt til det neste.
    1. Du ønsker å organisere prosjektet slik at, uansett grunn , Flash-filer er i en annen katalog fra klasse
      filer. Dette gjør faktisk fornuftig når du har et stort prosjekt med mange Flash-filer. Bare for å holde prosjektet struktur
      klarere, kan du bestemme deg for å beholde en "klasser" -mappen og en "flas" -mappen. Denne måten Flash-filer er gruppert sammen, men kan fortsatt
      aksjeklasser vanlige over hele prosjektet.

      Selvsagt kan du utføre disse oppgavene. Jeg ville ikke ha brakt dem opp hvis du ikke kunne. Jeg mener, men ikke så slem.

      Og, selvfølgelig, har du to alternativer for å gjøre dette. Begge involverer definere en kildebane
      . Man kan definere dem på applikasjonsnivå (i hvilket tilfelle kildebanen er tilgjengelig for alle Flash dokument åpner på den maskinen), eller på dokumentnivå (i hvilket tilfelle kildebanen er bare tilgjengelig for dette dokumentet). I tilfelle av grunnen 1 ovenfor, gjør programmet nivået kildebane forstand. Som for grunn # 2, vil dokumentet kildenivå banen være bedre

      For å definere et program-nivå Kilde Sti

      Åpne Flash-preferanser (på Mac:. Flash > Preferences, tvert PC: Edit > Preferences). Klikk på Action kategori til venstre. Nederst i vinduet som vises, klikker du på "Actionscript 3.0 Settings ..." knappen

      I vinduet som vises, er det tre områder:.. Kilde stier er toppen en

      Klikk på på "+" knappen og skriv inn din vei. Eller klikk på mappeknappen for å bla deg frem til det. Men du skriver det, når det er der, klikker OK til du er tilbake til Flash. På dette punktet, kan du fritt importere og bruke noen klasse fra den katalogen.

      For å definere et dokument-nivå Kilde Sti

      Med dokumentet åpent, åpner Publish Settings (gå til Fil > Publish Settings ...). Klikk på "Flash" -kategorien. Klikk på "Settings ..." knappen ved siden av Actionscript versjonskontroll. Et nytt vindu åpner seg, og dette vil være svært lik vinduet du får med programinnstillinger. Det er oppsettet er litt forskjellig, men ideen er den samme. Sørg for at du er på "Source Path" og skriv inn din vei. . Klikk "OK" og husk at dette er for dette dokumentet kun

      Mellom pakker og kilde stier, har du mange muligheter for å organisere klasser


      Trinn 9.: Sammensetning

      I forrige tutorial, fokuserte vi mye på arv. Det er en teknikk som kan betraktes motsatt-sår fra arv. Det kalles sammensetning
      .

      Nå er det ingenting galt med arv. Det er ikke som jeg satt på en trone av løgner og matet deg ondsinnet taradiddle i den siste opplæringen. Men du kan komme over uttrykket "foretrekker sammensetning i løpet av arv" i Objektorientert reise. Hvis (når) du kommer til å lære design patterns vil du absolutt høre det, og du vil selv se det manifest hvis du henger rundt avanserte programmerere lenge nok. Big Spaceship nylig (i skrivende stund) postet en diskusjon av metodikken de brukte når du utformer displayet pakke av deres github-ed Actionscript bibliotek. I det, de forklarer sine grunner for, i hovedsak, sammensetning i stedet for arv.

      Så hva er det? Den gode nyheten er at du allerede vet hvordan du gjør det, og har gjort det hele tiden. Blandingen er bare når en gjenstand lagrer et annet objekt i en eiendom. Hvis klassen har en egenskap kalt myLoader, og lagrer i det en Loader objekt, som klassen sies å komponere
      Loader objektet. Dette skjer hele tiden; Loader selv, faktisk, har en contentLoaderInfo eiendom som seg selv, komponerer
      en LoaderInfo objekt, som gir deg informasjon om selve laste


      Trinn 10:. Den subtile forskjellen Anmeldelser

      Composition virker som et fjernt fra arv, gjør det ikke? De to sannsynligvis ikke virke relatert i det hele tatt. Men tenk på dette: I den siste opplæringen, vi tilbrakte mesteparten av tiden gjør en Button101 klasse som utvidet Sprite. Dette gjorde det alt som Sprite er (og alt en Displayobject er, og alt en Display er, og ..., vel, husker du den diskusjonen). Dette var absolutt nyttig, og igjen, jeg er ikke her for å fortelle deg at det var feil måte å gjøre det.

      Men en alternativ
      måte å gjøre det ville være å ikke forlenge noe spesielt, og i stedet la Button101 klasse instantiate sin egen Sprite objekt, eller motta et mål Sprite objekt som en konstruktør parameter, eller på noen måte komponere
      Sprite og ikke arve
      det .

      Hvordan dette ville fungere kanskje ikke umiddelbart klart. Tillat meg å kaste en haug med kode på deg i en hagle-lignende innsats for å gjøre dette mer tydelig.

      Først, la oss vurdere den opprinnelige implementeringen. Her er, i sin helhet, den Button101 klasse fra forrige tutorial (du kan finne prosjektet i "button_tutorial" -mappen i nedlastingspakken):
      pakke {import flash.display.Shape; import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; import flash.text.TextFormat; public class Button101 strekker Sprite {private Var BGD: Shape; private Var labelField: Textfield; private Var _url: String; offentlig funksjon Button101 () {BGD = new Shape (); bgd.graphics.beginFill (0x999999, 1); bgd.graphics.drawRect (0, 0, 200, 50); addChild (BGD); labelField = new Textfield (); labelField.width = 200; labelField.height = 30; labelField.y = 15; Var format: tekstformat = new tekstformat (); format.align = "center"; format.size = 14; format.font = "Verdana"; labelField.defaultTextFormat = format; addChild (labelField); addEventListener (MouseEvent.ROLL_OVER, onOver); addEventListener (MouseEvent.ROLL_OUT, onOut); mouseChildren = false; buttonMode = true; } Offentlig funksjon sett etiketten (tekst: String): void {labelField.text = tekst; Var autoWidth: Number = Math.max (200, labelField.textWidth + 40); this.width = autoWidth; } Offentlig funksjon get etikett (): String {return labelField.text; } Private funksjon onOver (e: MouseEvent): void {bgd.alpha = 0,8; } Private funksjon onOut (e: MouseEvent): void {bgd.alpha = 1; } Offentlig funksjon sett url (theUrl: String): void {if (theUrl.indexOf ("http: //") == -1) {theUrl = "http: //" + theUrl; } _url = TheUrl; } Offentlig funksjon get url (): String {return _url; } Styre offentlig funksjon sett bredden (w: Number): void {labelField.width = w; bgd.width = w; } Overstyre offentlig funksjon satt høyde (h: Number): void {labelField.height = h; labelField.y = (h - labelField.textHeight) /2 - 3; bgd.height = H; }}}

      Og her er kodeutklippet fra document klassen som satt opp en Button101:
      knapp = new Button101 (); button.x = 10; button.y = 200; button.label = " Aktiv Tuts "; button.url =" http://active.tutsplus.com "; addChild (knapp); button.addEventListener (MouseEvent.CLICK, onButtonClick);

      Nå, her er tilsvarende kode, bare utnytte sammensetning stedet av arv. Dette er den oppdaterte Button101 klasse (endret og lagt linjene er uthevet):
      pakke {import flash.display.Shape; import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; import flash.text.TextFormat; public class Button101 {private Var _target: Sprite; private Var BGD: Shape; private Var labelField: Textfield; private Var _url: String; offentlig funksjon Button101 () {_target = new Sprite (); BGD = new Shape (); bgd.graphics.beginFill (0x999999, 1); bgd.graphics.drawRect (0, 0, 200, 50); _target.addChild (BGD); labelField = new Textfield (); labelField.width = 200; labelField.height = 30; labelField.y = 15; Var format: tekstformat = new tekstformat (); format.align = "center"; format.size = 14; format.font = "Verdana"; labelField.defaultTextFormat = format; _target.addChild (labelField); _target.addEventListener (MouseEvent.ROLL_OVER, onOver); _target.addEventListener (MouseEvent.ROLL_OUT, onOut); _target.mouseChildren = false; _target.buttonMode = true; } Offentlig funksjon sett etiketten (tekst: String): void {labelField.text = tekst; Var autoWidth: Number = Math.max (200, labelField.textWidth + 40); this.width = autoWidth; } Offentlig funksjon get etikett (): String {return labelField.text; } Private funksjon onOver (e: MouseEvent): void {bgd.alpha = 0,8; } Private funksjon onOut (e: MouseEvent): void {bgd.alpha = 1; } Offentlig funksjon sett url (theUrl: String): void {if (theUrl.indexOf ("http: //") == -1) {theUrl = "http: //" + theUrl; } _url = TheUrl; } Offentlig funksjon get url (): String {return _url; } Offentlig funksjon sett bredden (w: Number): void {labelField.width = w; bgd.width = w; } Offentlig funksjon satt høyde (h: Number): void {labelField.height = h; labelField.y = (h - labelField.textHeight) /2 - 3; bgd.height = H; } Offentlig funksjon get mål (): Sprite {return _target; }}}

      Og her er den oppdaterte kodebit pålagt å sette opp den oppdaterte Button101 (igjen, endringer uthevet):
      knapp = new Button101 (); button.target.x = 10; button.target .Y = 200; button.label = "Active Tuts"; button.url = "http://active.tutsplus.com";addChild(button.target);button.target.addEventListener(MouseEvent.CLICK, onButtonClick);

      Det er ikke mye mer kode. Det handler mer om tilsetting av _target eiendommen og bruken av den i stedet for den implisitte dette hvor Sprite-lignende ting var bekymret

      Her er en mer grundig sammenbrudd.

    2. Først på linje 8, fjerner vi strekker Sprite litt slik at vi ikke benytter arv.

      På linje 10, la vi målet eiendommen. Dette vil lagre vårt Sprite (det vil si, det komponerer
      Sprite) som tidligere
      blir arvet. Dette setter opp med komposisjon, og ikke arv.
    3. På linje 17, den første linjen i konstruktøren, skaper vi en ny Sprite og stash det i vår _target eiendom. På dette punktet, etter vi med hell bruker komposisjon.
    4. På linjene 22, 33 og 35-39, vi har rett og slett lagt en referanse til _target foran metodekall som tidligere ble levert av
      Sprite super. Fordi vi ikke strekker Sprite lenger, har vi ikke lenger et addChild eller addEventListener metode, etter eller mouseChildren eller buttonMode egenskaper. Vi, derimot, har
      en Sprite som vi kan kalle disse tingene, så overfører vi
      ansvar der.
    5. I linjene 67 og 71, må vi fjerne overstyring søkeord, så vi skal ikke gå noe, så det er ingenting å overstyre.

      På slutten av klassen (linje 77-79), legger vi en helt ny metode. Det er en getter funksjon som returnerer en referanse til Home komponert Sprite. Dette trinnet er avgjørende for endringene i document.
    6. I document, endringene alle involverer regissere Sprite-lignende oppførsel til målet på knappen, snarere enn til knappen
      selv. For eksempel på linjene 2 og 3, i stedet for å plassere knappen objekt, vi posisjonere målrette
      på knappen. Tilsvarende, etter at vi ikke kan legge til knappen som et barn til listevisning, men vi kan
      legge button.target.

      Så sluttresultatet skal være identiske. Forskjellen er under panseret, i hvordan det Button101 er satt opp.

      Nå, hvis det fungerer, hvorfor er det en dårlig idé? Det er vanligvis en ganske subjektiv ting å anser riktigheten av koden. På den ene side, hvis det fungerer, så det kan ikke være så ille. På den annen side, hvis koden skal være opprettholdes
      , da vedlikehold av koden er like viktig å være funksjonell.

      kode presenteres her ikke er vedlikeholdsvennlig. Det største problemet er her (i Button101BadIdea):
      _clickField.text = _text;

      Vi har nettopp låst knapp klassen til å gjøre en ting og en ting bare: å sette tekst til et Textfield. Nå er gitt, er det blitt satt opp til å bruke en hvilken som helst tekst og noen Textfield, men egentlig denne knappen har en meget bestemt formål. Hvis du noensinne
      trengte en knapp for å gjøre noe annet - noe Anmeldelser annet - du vil bli sittende fast med å måtte gjøre flere knappe klasser. Selv om utseendet på knappen var å være den samme


      Trinn 15:.? Jeg kan har bedre Solushun

      Selvfølgelig, jo bedre løsning var den som allerede er presentert i de foregående tutorials ( se "button_tutorial" -prosjektet i nedlastingspakken hvis du trenger en oppfriskning). Men hva gjør det bedre?

      For det første, er det Button101 klasse langt mer gjenbrukbare hvis den ikke anta at et klikk skal resultere på å sette inn tekst i et Textfield. Om nødvendig, kan det endelige resultatet fremdeles oppnås, men så kan hvilken som helst annen grunn. Men vi oppnå resultatet ikke innenfor Button101 objekt; i stedet, er at logikken i det document objektet. Eller, mer generelt, er at logikken i objektet som "eier" Button101 objektet.

      Nå kan objektet som eier Button101 objektet være stort sett alle objekt som krever en knapp. Behovet for knappen er deretter fulgt av den spesifikke sluttresultatet nødvendig når knappen klikkes. Og det er ansvaret til objektet som trenger knappen, ikke selve knappen.

      Så det vi har, i den opprinnelige og bedre løsning, er en gjenstand som komponerer et annet objekt. Objektet som blir sammensatt er ganske selvstendig, men gir visse felles egenskaper og metoder som det kan tilpasses til en viss grad. Objektet gjør komponering er i kontroll, og manipulerer det komponerte objekt gjennom sine offentlige eiendommer og metoder.

      Dette forholdet er den grunnleggende byggesteinen i større programmer, og fokus for resten av denne opplæringen.


      Trinn 16: hierarkiet av Composition

      For å aktivere to-veis kommunikasjon mellom klasser, må vi begynne å tenke i form av hierarkier av komposisjon. Som regel hvis objekt A komponerer objekt B, da det motsatte er desidert ikke sant. Jeg må iterere det, naturligvis, det finnes unntak fra denne regelen. import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *; import flash.events. *;