Rubiin: #kloon vs #dup

Madala koopia olemus

Ruby-doci sõnul saab nii # klooni kui ka #dup abil luua objekti pinnapealse koopia, mis läbib ainult ühe keerukuse kihi, mis tähendab, et kopeeritakse obj eksemplari muutujad, kuid mitte objektid, millele nad viitavad. Neil kõigil oleks samad atribuudid; ühe muutmine tooks kaasa teise muutmise. Kuid #clone teeb kahte asja, mis erinevad kui #dup:

1) # kloon säilitab obj külmutatud või riknenud oleku. arvestades, et #dup muudaks selle määrdunuks.

a = [1, 2, 3, 4, 5]
a.külm
a_clone = a.clone
a_clone << 6 # => ei saa külmutatud massiivi muuta
a_dup = a.dup
a_dup << 6 # => [1, 2, 3, 4, 5, 6]

Enamikus objektorienteeritud programmeerimiskeeltes on objektid üldiselt muudetavad (või rikutud) piiratud eranditega. Ruby kohtuasjas on vahetatavus eksemplari, mitte kogu klassi omadus. Iga eksemplar võib muutumatuks muutuda, kui helistate #freeze. See muudab objekti konstandiks ja kapseldamise lihtsamaks. Seega, kui osa objekti olekust on külmunud, saavad juurdepääsujuhtivad meetodid selle muutumatu objekti tagastada välistele helistajatele, kartmata, et need helistajad saavad objekti olekut muuta.

klassi kala
  attr_accessor: nimi
  @@ kõik = []
  def lähtestama (nimi)
    @ nimi = nimi
    @@ kõik << ise
  lõpp
  def self.all
    @@ all.dup.freeze
  lõpp
lõpp
kala = Fish.all
kala << Human.new ("John") # => ei saa külmutatud massiivi muuta

Ruby külmutab automaatselt ka räsiklahvi, kui võti on string. Nii kui algne string hiljem muutub, ei mõjuta see räsivõtit.

kala = {“Dory” => {: name => “Dory”,: type => “Regal Blue Tang”},
         “Nemo” => {: name => “Nemo”, type => “Clownfish”}
}
fish.keys.first.frozen? # => tõsi
fish.keys.first.replace ("Hull sinine kala") # => ei saa külmutatud stringi muuta

2) #clone kopeerib objekti kõik singleton-meetodid, kuid #dup seda ei toeta.

klassi kala
  attr_accessor: nimi
  def initsialiseerima (nimi)
    @ nimi = nimi
  lõpp
lõpp
dory = Fish.new ("Dory")
def dory.whale_talk
  "Mmmmoooooowaaaaah ..."
lõpp
dory_clone = dory.clone
dory_clone.whale_talk # => "Mmmmoooooowaaaaah ..."
dory_dup = dory.dup
dory_dup.whale_talk # => määratlemata meetod `whale_talk’ # # kala jaoks: 0x0055f7b7917e90 @ name = "Dory">
Üldiselt võib kloonil ja duplil olla järeltulijate klassides erinev semantika. Kui klooni kasutatakse objekti, sealhulgas selle sisemise oleku dubleerimiseks, kasutab dup tavaliselt uue eksemplari loomiseks alaneva objekti klassi.

Põhimõtteliselt annavad nii kloon kui ka #dup objektist pinnapealsed koopiad. # kloon kopeerib kõike: sisemist olekut, üksikuid meetodeid jne. #dup kopeerib ainult objekti sisu (pluss rikutud olek).

Sügavat koopiat kasutatakse seevastu stsenaariumide korral, kus luuakse uus koopia (kloon) ilma viideteta algsetele andmetele (nende kahe erinevuse kohta lisateabe leiate minu teisest postitusest)

*** Ole teadlik ***

Rails 4.0-s käituvad #clone ja #dup pisut erinevalt. # kloon on ActiveRecordi objekti täpne koopia. Nad jagavad kõiki atribuute, isegi peamist võtit.

Ruby kloonimeetodiga identne. See on "madal" koopia. Pange tähele, et teie atribuute ei kopeerita. See tähendab, et klooni atribuutide muutmine muudab originaali, kuna mõlemad osutavad samadele atribuutidele räsi. Kui vajate oma atribuutide räsi koopiat, kasutage meetodit #dup.

Ehkki #dup peetakse endiselt pinnapealseks eksemplariks, pole sellel originaali suhtes otsest seost; ja seega ei tekita dubleeritud objekti atribuutide muutmine algset.

Dupeeritud objektidel pole ID-d määratud ja neid käsitletakse uute kirjetena. Pange tähele, et see on pinnapealne koopia, kuna see kopeerib ainult objekti atribuute, mitte selle seoseid. „Sügava” eksemplari ulatus on rakendusespetsiifiline ja seetõttu jäetakse rakendus vastavalt vajadusele selle rakendamiseks.
[1] pry> original = User.find (1)
=> # 
[2] pry> original.clone
=> # 
[3] pry> original.dup
=> #