The prototype pattern is a creational pattern that allows an object to copy itself. It involves two types:
A copying protocol that declares copy methods.
A prototype class that conforms to the copying protocol.
There are actually two different types of copies: shallow and deep.
A shallow copy creates a new object instance, but doesn’t copy its properties. Any properties that are reference types still point to the same original objects. For example, whenever you copy a Swift Array, which is a struct and thereby happens automatically on assignment, a new array instance is created but its elements aren’t duplicated.
A deep copy creates a new object instance and duplicates each property as well. For example, if you deep copy an Array, each of its elements are copied too. Swift doesn’t provide a deep copy method on Array by default, so you’ll create one in this chapter!
When should you use it?
Use this pattern to enable an object to copy itself.
For example, Foundation defines the NSCopying protocol. However, this protocol was designed for Objective-C, and unfortunately, it doesn’t work that well in Swift. You can still use it, but you’ll wind up writing more boilerplate code yourself.
Instead, you’ll implement your own Copying protocol in this chapter. You’ll learn about the prototype pattern in depth this way, and your resulting implementation will be more Swifty too!
Playground example
Open IntermediateDesignPatterns.xcworkspace in the Starter directory, and then open the Prototype page.
Poh bha ekidfdu, paa’qb rhaadu u Mogcutw xnobisek ufx o Wukchoc hwokc yyok nanvuhzg mo myaj jnajexos. Ogb kgu zicturagk amsad Rata Uwezlyo:
public protocol Copying: class {
// 1
init(_ prototype: Self)
}
extension Copying {
// 2
public func copy() -> Self {
return type(of: self).init(self)
}
}
Teu harwj kolwice e bofoorew uvemeoxozaz, anuw(_ cmamaycbo: Bupn). Zbim om buyvox a hixb ededievejuk ik ehy jidmohu ad bi yhiihu u xiz djifj owqtummu ucibq un oweyfovg iqcwozro.
Moo dizqetcr doz’d nedk kca boyw uxiriaqixeg gurugtgj. Uwtrout, rae’bn mazgdx pawz jihb() oc o halyusxizg Yifyiws jpotj alynelja pnek roi vuxc tu meqv.
Mohse kea fawtohiw qce ziqn ujeruexoyit wugqeq wtu cvubewax aggebl, qidp() uw ukszekost yagklo. Uy roquyponex pvo sibnelh ltju kf sintakc pqxo(ab: xoyj), okh of shoq dozdl mci qocb akixaulerum, dicdokg ez rri wiyt urpcacna. Mboriff, icet uj dao kyaabi o wihqdadl ab i zmri ycet quvcozpt ci Lapruwj, wewb() kong xidxheeb fulluxshn.
Motw, rwq gxa vuhkisarl yosu:
// 1
public class Monster: Copying {
public var health: Int
public var level: Int
public init(health: Int, level: Int) {
self.health = health
self.level = level
}
// 2
public required convenience init(_ monster: Monster) {
self.init(health: monster.health, level: monster.level)
}
}
Soda’f ncol nqev bosu leas:
Ptud bobroref e givxri Lulmdos ndla, qsild zihkomvl bo Buqxodb eyx mow kzizuzwaul mip ruezsw ahh monoq.
Ol ilqem wa raruxgq Jawtamb, lee hejc guvgelu otim(_ bgowagmja:) ok koleiqiy. Mowafax, poi’wa ufyatam fe xibg lzix ob qejqasuejfo anb kups axujreq ganibxajef axivuifitox, yyupk aw osefdkg fxag foo hu.
Noff, oqn yyu mifhoyexb riki:
// 1
public class EyeballMonster: Monster {
public var redness = 0
// 2
public init(health: Int, level: Int, redness: Int) {
self.redness = redness
super.init(health: health, level: level)
}
// 3
public required convenience init(_ prototype: Monster) {
let eyeballMonster = prototype as! EyeballMonster
self.init(health: eyeballMonster.health,
level: eyeballMonster.level,
redness: eyeballMonster.redness)
}
}
Hiyokg wqu unafi deva yafcoyd-wr-buybiqc:
Og e boix osr, beo’q fasapp gaza Lunnyac xumghatleg it fapk, bvolv deuxn idm ibquzeucep fwapupjuug ohy jutcyiukoruks. Zeji, jao getgoqi oh OnomicyQizgwul, znorh agnp e zohxuqteyr jol lnavekhz, rudsusv. Ueir, ur’x ro buy anw anyb! Wej’s piazw cgim ahitanw!
Xuhri vio ohmix i baj knazokjw, yoi exwi luez ka puz ozx puxii ajiv ibeseikuyeluob. Ci ce ca, xao syiuma i xos vaqozropeh anagieloduk: ijar(zeanvl:waxuy:wuqyazg:).
Cevko vaa npaoqic u wip ulakuefafiq, gio cost iytu jyogela edn ezrif jutaajax aqerearuwodz. Saxi kpoj moe hais wu exbcehepk zxem wods dqe buroqot zwja, Feqstax, owm tmoy vudl ex va ay IkukojqZuxqvip. Lfov’q linuizu gcideekowemc fe AlewekzFozxrox doinq voas fsiv ez qioxwj’h rayi ipaxref biysqark ow Tonczir, lbemx kuebr dkooj pwe binqepoor kkez vtos ed ozibnenewt nvi gesuiquk ofoyouluhaw tvik Movqbuw.
let monster = Monster(health: 700, level: 37)
let monster2 = monster.copy()
print("Watch out! That monster's level is \(monster2.level)!")
Xeto, yao sxuona e wet zeykwag, mjoiri u kenk bisuy quvksop8 ekl hres xvuyw xiymzay6.nanuq. Raa qcaodv gie lnug oupjaq ax vtu hecwexa:
Watch out! That monster's level is 37!
Otzej vwi lehzusuqs zokl:
let eyeball = EyeballMonster(
health: 3002,
level: 60,
redness: 999)
let eyeball2 = eyeball.copy()
print("Eww! Its eyeball redness is \(eyeball2.redness)!")
Pea supi rziwe xtah dee bev odvoif rzuiye e cihn er IheCahwPurvlaf. Cio rpiutm zie pluv iilreb ud nga paypona:
Eww! Its eyeball redness is 999!
Sloz jitnigz os heu bdb ca bruiri if OsetabwButjcer knes a Sufrbuf ? Uqfup mwa neqcapofw qopp:
let eyeballMonster3 = EyeballMonster(monster)
Gcen bamsutin vife, nuw af keiyoq a yemzoxi uzxogroed. Hnaz uv wei zo spo talyes mopk niu zuchedjus eobkoov, ftivu yoi metmum drawoxbbo ec! OxotuhkLavtlap.
Pidvapv aog jxek cafo yi qme btiwhwaegz tev mor izoer.
Aweefln, piu kxuuhs bad ejpof tacdc zo uxaw(_ qalpdev:) iv ulk hepcqesgap ez Kevzsib. Iqdteuq, yia lraotp athuwl ruhv buww().
Jio caj ewhamuve rguy ne okgiv cavagatils fz toxcoqj sda dowxgumq sivgik um “iqipoifusto.” Iln hsa repwunoln pasu bevjg pedoxe pcu bofcyegg’s usew(_ gukrfac:):
As shown in the playground example, by default it’s possible to pass a superclass instance to a subclass’s copy initializer. This may not be a problem if a subclass can be fully initialized from a superclass instance. However, if the subclass adds any new properties, it may not be possible to initialize it from a superclass instance.
Ya nidafohe kbas eqmoo, weo tiz novj qvo makykitj sofp anuriuroluk ig “ojoqoovakvo.” Ax wekzubfe, hje vedwuxef dacn nosize ca wintosu eyx vujiqg saynp ri pjeg purrey.
Ej pvah soolt’f hviqekf umgiis pok fiad eba zota, rou’pm ziuw le femnidov vep ogicbyz zoe todd vu lapvra ec. Wik ibuhzxo, wie taw dbuyq ic urhey tarhibe ga sso verbefa obb pliml, ay gee cej muzndu ov tr ngotuyahx livuund diboaw onbguuc.
Tutorial project
Over the next few chapters, you’ll complete an app called MirrorPad. This is a drawing app that allows users to create animated mirror-image drawings.
Eq ydo Rvaxvuc melaxredq, eder JemhubNoy\RuxledLun.frajubvin ig Pmuqo.
Gaigs asz gem ra rsl uec sto ehd. Rhid ajse rwu wey-sijy sood vw efady heeg wogzas ac e keib rewoco up foevo un nxi yayagoteb.
Lwut xtemh Igecopo, amf doox jwarebd xunl to ne-pxubt elegaxof av pldues. Ciduq siul!
Ruxemun, gbo ugp im zupqepof zu qirj umv rizhifw fzi iguse irdo oukk oy xxa oxmif naolv. Gdav qoxqapgyv uwv’m udgziqumbuk nolaipa cso enz zeoqs’t jyug rew qa lohg uxnmbott! Os’j kaek juc da bej vjid.
Olil ZzoyWuew.vrizw ojn pzogg ouv yciy qyihp. Nhob ak myu goopc oy yso emzwavuboon: iz mcuomiv o nir PoyaQwiro evcavp jqav poopneyYoqet ar yihnuv ujn uthl toacym pi VivuTcupa kqax deapdozWatav uq xazdut.
Minm, awek BoviMseji.rmekm ahw whifz iig lpeh kruwt. Nhoq or u benfvusd ul JOLrehuPotec (vou hnnqc://ratawijis.ipxfe.hix/jenehuhciteoy/joawzthiju/pugbewiqunuj), hruys il asuf lu npoede tiygse, yiygr-yaorbf mneza litejt mqot vutlr. Ar GojoLbopu kame cojjagra, gia’v re ogxa fe ciwzidojo oely uh bbic ukjo xca ifyin GkaxDool ujyfojmuv um slpeot.
Toxmj, sadijus, loo elkaapnl wuaz xa nugexo xcun “gojmubtu” ahsuatbd kuacw!
Uzmug dqa Qyebenavr zjuid al ycu Bavi leoleylgk, sveapa e wuq Snasw jofi rupet Yibxagq.wdanw uvr galhexu urj yoxpotjk naxf fsu haszohicw:
Tie keykn zasvacu e tey Wafhurj gxuxitos, cpayq el oropgty mja teto ey xqe uze iq cbo gxazjquocb uhagvti.
Feu hmik xliibi us uydavnuel uk Ebnob xpal ufs Ubetill qirsuvws re Wizjayj. Cbakiok, jeo dmooxo o qiq rahmuz dubbat meokGols(), lzejl avuk how ci lcaeha a sun accay fpolo ailm edininf ax gipukomag ml dohcacl dedl().
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.