af Payal Gupta

kopiering af et objekt har altid været en væsentlig del i kodningsparadigmet. Det være sig i hurtig, Objective-C, JAVA eller ethvert andet sprog, skal vi altid kopiere et objekt til brug i forskellige sammenhænge.

i denne artikel vil vi diskutere i detaljer, hvordan man kopierer forskellige datatyper i hurtig og hvordan de opfører sig under forskellige omstændigheder.

værdi-og referencetyper

alle datatyper i hurtig falder stort set i to kategorier, nemlig værdityper og referencetyper.

  • Værditype — hver forekomst opbevarer en unik kopi af dens data. Datatyper, der falder ind under denne kategori, inkluderer – all the basic data types, struct, enum, array, tuples.
  • referencetype — forekomster deler en enkelt kopi af dataene, og typen defineres normalt som en class.

det mest karakteristiske træk ved begge typer ligger i deres kopieringsadfærd.

Hvad er dyb og overfladisk kopi?

en forekomst, uanset om det er en værditype eller en referencetype, kan kopieres på en af følgende måder:

Deep copy — duplikerer alt

  • med en dyb kopi kopieres ethvert objekt, der peges på af kilden, og kopien peges på af destinationen. Så to helt separate objekter vil blive oprettet.
  • Samlinger — en dyb kopi af en samling er to samlinger med alle elementerne i den oprindelige samling duplikeret.
  • mindre tilbøjelige til raceforhold og klarer sig godt i et flertrådet miljø — ændringer i et objekt vil ikke have nogen effekt på et andet objekt.
  • værdityper kopieres dybt.

i ovenstående kode,

  • linje 1: arr1 — array (en værditype) af strenge
  • linje 2: arr1 er tildelt arr2. Dette vil skabe en dyb kopi af arr1 og derefter tildele den kopi til arr2
  • linjer 7 til 11: eventuelle ændringer udført i arr2 reflekter ikke i arr1.

dette er, hvad deep copy er — helt separate tilfælde. Det samme koncept fungerer med alle værdityper.

i nogle scenarier, dvs.når en værditype indeholder indlejrede referencetyper, afslører deep copy en anden form for adfærd. Det får vi at se i de kommende afsnit.

lav kopi — duplikater så lidt som muligt

  • med en lav kopi peges ethvert objekt, som kilden peger på, også af destinationen. Så kun et objekt vil blive oprettet i hukommelsen.
  • Samlinger — en overfladisk kopi af en samling er en kopi af samlingsstrukturen, ikke elementerne. Med en lav kopi deler to samlinger nu de enkelte elementer.
  • hurtigere — kun referencen kopieres.
  • kopiering af referencetyper opretter en lav kopi.

i ovenstående kode,

  • linjer 1 til 8: Address klassetype
  • linje 10: a1 — en forekomst af Address type
  • linje 11: a1 er tildelt a2. Dette vil skabe en lav kopi af a1 og derefter tildele den kopi til a2, det er kun referencen kopieres til a2.
  • linjer 16 til 19: eventuelle ændringer udført i a2 vil helt sikkert afspejle i a1.

i ovenstående illustration kan vi se, at både a1 og a2 peger på den samme hukommelsesadresse.

kopiering af referencetyper dybt

fra nu af ved vi, at når vi prøver at kopiere en referencetype, kopieres kun referencen til objektet. Der oprettes ikke noget nyt objekt. Hvad hvis vi vil oprette et helt separat objekt?

vi kan oprette en dyb kopi af referencetypen ved hjælp af copy() – metoden. Ifølge dokumentationen,

kopi() — returnerer objektet returneret af copy(with:).

dette er en bekvemmelighedsmetode for klasser, der vedtager protokollen NSCopying. En undtagelse er rejst, hvis der ikke er nogen implementering for copy(with:).

lad os omstrukturere Address class vi oprettede i kodestykke 2 for at overholde protokollen NSCopying.

i ovenstående kode,

  • linjer 1 til 14: Address klassetype overholder NSCopying og implementerer copy(with:) metode
  • linje 16: a1 – en forekomst af Address type
  • linje 17: a1 er tildelt a2 ved hjælp af copy() metode. Dette vil skabe en dyb kopi af a1 og derefter tildele denne kopi til a2, det er et helt nyt objekt vil blive oprettet.
  • linjer 22 Til 25: eventuelle ændringer udført i a2 afspejler ikke i a1 .

som det fremgår af ovenstående illustration, peger både a1 og a2 på forskellige hukommelsessteder.

lad os se på et andet eksempel. Denne gang ser vi, hvordan det fungerer med indlejrede referencetyper — en referencetype, der indeholder en anden referencetype.

i ovenstående kode,

  • linje 22: en dyb kopi af p1 er tildelt p2 ved hjælp af copy() – metoden. Dette indebærer, at enhver ændring i en af dem ikke må have nogen effekt på den anden.
  • linjerne 27 Til 28: p2's name og city værdierne ændres. Disse må ikke afspejle i p1.
  • linje 30: p1's nameer som forventet, men dens city? Det burde være "Mumbai" burde det ikke? Men vi kan ikke se, at det sker. "Bangalore" var kun for p2 ikke? JEP … præcis.?

dyb kopi…!? Det var ikke forventet af dig. Du sagde, du ville kopiere alt. Og nu opfører du dig sådan. Hvorfor Åh hvorfor..?! Hvad gør jeg nu? Til dig

gå ikke i panik. Lad os se på, hvad hukommelsesadresser har at sige i dette.

fra ovenstående illustration kan vi se, at

  • p1 og p2 peg på forskellige hukommelsessteder som forventet.
  • men deres address variabler peger stadig på samme sted. Det betyder, at selv efter at have kopieret dem dybt, kopieres kun referencerne — det vil sige en lav kopi selvfølgelig.

Bemærk venligst: hver gang vi kopierer en referencetype, oprettes en lav kopi som standard, indtil vi udtrykkeligt angiver, at den skal kopieres dybt.

func copy(with zone: NSZone? = nil) -> Any{ let person = Person(self.name, self.address) return person}

i ovenstående metode implementerede vi tidligere for Person klassen, vi har oprettet en ny instans ved at kopiere adressen med self.address. Dette kopierer kun henvisningen til adresseobjektet. Dette er grunden til, at både p1 og p2's address peger på samme sted.

så kopiering af objektet ved hjælp af copy() – metoden skaber ikke en ægte dyb kopi af objektet.

at duplikere et referenceobjekt fuldstændigt: referencetypen sammen med alle de indlejrede referencetyper skal kopieres med copy() – metoden.

let person = Person(self.name, self.address.copy() as? Address)

brug af ovenstående kode i func copy(with zone: NSZone? = nil) -> enhver metode får alt til at fungere. Du kan se det fra nedenstående illustration.

ægte dyb kopi-Reference og værdityper

vi har allerede set, hvordan vi kan oprette en dyb kopi af referencetyperne. Selvfølgelig kan vi gøre det med alle de indlejrede referencetyper.

men hvad med den indlejrede referencetype i en værditype, det vil sige en række objekter eller en referencetypevariabel i en struktur eller måske en tupel? Kan vi løse det ved hjælp af copy() også? Nej, det kan vi faktisk ikke. Metoden copy() kræver implementering af NSCopying protokol, som kun fungerer for NSObject underklasser. Værdityper understøtter ikke nedarvning, så vi kan ikke bruge copy() sammen med dem.

i linje 2 er kun strukturen af arr1 dybt kopieret, men Address objekterne inde i det er stadig lavt kopieret. Du kan se det fra nedenstående hukommelseskortkort.

elementerne i begge arr1 og arr2 peger begge på de samme hukommelsessteder. Dette skyldes af samme grund — referencetyper kopieres som standard lavt.

serialisering og derefter de-serialisering af et objekt skaber altid et helt nyt objekt. Det gælder for både værdityper såvel som referencetyperne.

her er nogle API ‘ er, som vi kan bruge til at serialisere og de-serialisere data:

  1. NSCoding-en protokol, der gør det muligt at kodes og afkodes et objekt til arkivering og distribution. Det fungerer kun med class skriv objekter, da det kræver arv fra NSObject .
  2. Codable — gør dine datatyper kodelige og dekodelige for kompatibilitet med eksterne repræsentationer som JSON. Det fungerer for begge værdityper — struct, array, tuple, basic data typessamt referencetyper — class .

lad os omstrukturere Address – klassen lidt længere for at overholde Codable – protokollen og fjerne al NSCopying – koden, som vi tilføjede tidligere i kodestykke 3.

i ovenstående kode opretter linjer 11-13 en ægte dyb kopi af arr1. Nedenfor er illustrationen, der giver et klart billede af hukommelsesstederne.

kopier på Skriv

kopier på Skriv er en optimeringsteknik, der hjælper med at øge ydeevnen, når du kopierer værdityper.

lad os sige, at vi kopierer en enkelt streng eller Int eller måske en anden værditype — vi står ikke over for nogen afgørende ydelsesproblemer i så fald. Men hvad med når vi kopierer en række tusinder af elementer? Vil det stadig ikke skabe nogen ydelsesproblemer? Hvad hvis vi bare kopierer det og ikke foretager nogen ændringer i den kopi? Er det ikke ekstra hukommelse, vi brugte bare spild i så fald?

her kommer begrebet kopi i skrivning — ved kopiering peger hver reference på den samme hukommelsesadresse. Det er kun, når en af referencerne ændrer de underliggende data, der hurtigt faktisk kopierer den oprindelige forekomst og foretager ændringen.

det vil sige, om det er dyb kopi eller lav kopi, en ny kopi oprettes ikke, før vi foretager en ændring i et af objekterne.

i ovenstående kode,

  • linje 2: en dyb kopi af arr1 er tildelt arr2
  • linjer 4 og 5: arr1 og arr2 peger stadig på den samme hukommelsesadresse
  • linje 7: ændringer foretaget i arr2
  • linjer 9 og 10: arr1 og arr2 peger nu på forskellige hukommelsesplaceringer

nu ved du mere om dybe og lave kopier, og hvordan de opfører sig i forskellige scenarier med forskellige datatyper. Du kan prøve dem med dit eget sæt eksempler og se, hvilke resultater du får.

yderligere læsning

glem ikke at læse mine andre artikler:

  1. alt om Kodbar i Hurtig 4
  2. alt hvad du altid har ønsket at vide om underretninger i iOS
  3. Farvelæg det med gradienter — iOS
  4. kodning til iOS 11: Sådan trækker du & slip ind i samlinger & tabeller
  5. alt hvad du behøver at vide om i dag udvidelser i iOS 10
  6. uicollectionvisecell valg gjort nemt..!!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.