|
[ pn.bl @ 16.08.2010. 22:06 ] @
| Napravim novi objekat klase, dodijelim mu određene vrijednosti, napravim drugi, novi, objekat iste klase i želim da već dodijeljene vrijednosti prvom objektu proslijedim i drugom a da ne bude u pitanju referenca već dva različita objekta.
PRIMJER
Code (vbnet):Public Class Igrac
Dim ime as String
Dim visina as Decimal
Dim pozicija as Short
Dim ImeEkipe as String
Sub New()
ime = ""
visina = 0
pozicija = 1
ImeEkipe = ""
End Sub
End Class
....
dim igracA as new Igrac
igrac.ime = "Pavle"
igrac.ImeEkipe = "Sampion"
dim igracB as new Igrac
igracB=igracA
igracB.ime="Brane"
.......
Umjesto da sad imam dva igraca Pavle, Brane, dobio sam referencu na prvi objekat. Ima li drugačiji način dodijeljivanja vrijednosti drugom objektu sem ručnog, jer u situaciji kad klasa ima više svojstva, 30, za dodijeli puno je ručnog koda....
.......
dim igracB as new Igrac
igracB.ime="Brane"
igracB.imeEkipe=igracA.ImeEkipe
igracB.nesto=igracA.nesto
........
A ne želim, nemam potrebu da svojstvo imeEkipe učinim djeljenim, Private Shared ImeEkipe.
[Ovu poruku je menjao mmix dana 17.08.2010. u 09:30 GMT+1] |
[ bojan21 @ 16.08.2010. 23:15 ] @
Ima dosta nacina da se to uradi, sve zavisi od toga sta sve hoces da kopiras (vrednosne i/ili referentne tipove). Konkretno za taj primer koji si naveo, mislim da bi ti bilo najlakse da u okviru klase napises novu metodu koja bi kopirala vrednosti atributa iz drugog objekta iste klase. Nesto ovako:
Code (vbnet):
Class Test
Private myString As String = ""
Private myInt As Integer = 0
'constructor
Public Sub New()
End Sub
Public Sub CloneProperties(source As Test)
Me.myString = source.myString
Me.myInt = source.myInt
End Sub
End Class
I onda, ako hoces da kopiras atribute, to radis ovako:
Code (vbnet):
Dim test1 As New Test()
test1.myString = "nesto"
test1.myInt = 21
Dim test2 As New Test()
'kopiras atribute iz "test1" u "test2"
test2.CloneProperties(test1)
Naravno, mogao si ovo da uradis na drugaciji nacin (staticka metoda, direktno da vraca objekat tipa "Test", i sl).
Procitaj tekst sa ovog linka, moze dosta da ti pomogne: http://www.csharp411.com/c-object-clone-wars/
Pozdrav
[ mmix @ 17.08.2010. 08:31 ] @
Mozes i da kloniras instancu ako su sva polja u njemu stringovi ili value tipovi
[ pn.bl @ 17.08.2010. 10:23 ] @
Citat: Naravno, mogao si ovo da uradis na drugaciji nacin (staticka metoda, direktno da vraca objekat tipa "Test", i sl).
Misliš na ovako nešto
Code:
VB.NET
Public Function CreateNewObject()
Dim newIgrac As New Igrac
With newIgrac
.ime = Me.ime
.visina = Me.visina
.pozicija = Me.pozicija
.ImeEkipe = Me.imeEkipe
End With
Return newIgrac
End Function
...
Dim igracA as new Igrac
igrac.ime = "Pavle"
igrac.ImeEkipe = "Sampion"
dim igracB as new Igrac
igracB=igracA.CreateNewObject()
igracB.ime="Brane"
[ pn.bl @ 17.08.2010. 10:26 ] @
Citat: Mozes i da kloniras instancu ako su sva polja u njemu stringovi ili value tipovi.
Ako se objekat klonira zar se ne dešava shallow copy, referenca na taj objekat? Ili griješim?
Ja bih htjeo biti siguran da sam napravio putpuno nov objekat, hard copy.
[ Mikelly @ 17.08.2010. 10:32 ] @
Mozda preko refleksije. Pisem napamet:
Code:
void Clone(source, destination)
{
Type type = typeof(source);
FieldInfo[] fields = type.GetFields();
foreach(FieldInfo field in fields) field.SetValue(destination, field.GetValue(source));
}
[ mmix @ 17.08.2010. 10:53 ] @
Shallow copy nije to sto ti mislis da jeste. Shallow copy je nova referenca i novi alocirani blok memorije u koje su prekopirana sva polja iz originalnog objekta. U praksi to znaci da objekatA.X nije na istoj memorijskoj lokaciji kao objekatB.X, ali isto znaci da objekatA.referenca pokazuje na isti objekat kao objekatB.reference (deep copy resava itaj problem ali ne postoji implicitni deepcopy, moras da uradis neki svoj mehaniam ili preko ICloneable ili preko serijalizacije). Medjutim, dok god su te reference samo stringovi nemas problem (posto su stringovi immutable nevazno je da li pokazuje na kopiju stringa ili na originalni string, ne mozes ga menjati), jedini problem moze da bude ako je referenca na instancu neke druge klase.
TO sto ti mislis da je shallow copy, tj kreiranje nove reference na isti objekat, se u .NETu desava prostom dodelom reference (objekatB = objekatA) cime kreiras novi root za GC i onda oni pokazuju na isti memorijski blok.
Dakle ako uradis objekatB = objekatA.Clone() to je kopija sa svojim vrednostima.
[ Boris B. @ 17.08.2010. 11:11 ] @
Citat: Mikelly
Mozda preko refleksije. Pisem napamet:
Code:
void Clone(source, destination)
{
Type type = typeof(source);
FieldInfo[] fields = type.GetFields();
foreach(FieldInfo field in fields) field.SetValue(destination, field.GetValue(source));
}
Tako nesto nece napraviti deep kopiju objekta, svi enkapsulirani tipovi ce biti samo ponovo referencirani umesto kopirani. Neki genericki nacin za deep clone nazalost ne postoji, izmedju ostalog jer nemaju sve klase parameterless konstruktor, a i kad bi imale niko ne garantuje pravilnu inicijalizaciju eventualnih non-public clanova.
Treba onako kako je mmix rekao, znaci implementiras ICloneable i teras svoju logiku:
Code (csharp):
public class Auto : ICloneable
{
public int Tockova ;
private int _tezina ;
public object Clone ()
{
return new Auto { Tockova = Tockova, _tezina = _tezina };
}
}
Edit: vidim da je kolega vec reagovao, bio sam spor :)
[ mmix @ 17.08.2010. 11:39 ] @
Iskreno, ja vise preferiram (de)serijalizaciju ako je potreban deep copy sa referencama, sporije je dosta, ali sam 100% siguran da nigde nije zalutala dupla referenca 
[ Majestic @ 17.08.2010. 11:54 ] @
Hehe i ja sam vodio "ratove" s tim jednom  , kao sto rece @mmx serijalizacija je najbolji pristup
ukoliko brzina nije problem. Evo par linkova koje cuvam u bookmarku na tu temu:
http://www.csharp411.com/c-object-clone-wars/
http://www.codeproject.com/KB/cs/ShallowVsDeepCopy.aspx
http://stackoverflow.com/quest...n-object-in-net-c-specifically
[ pn.bl @ 17.08.2010. 12:34 ] @
Citat: mmix:
Medjutim, dok god su te reference samo stringovi nemas problem (posto su stringovi immutable nevazno je da li pokazuje na kopiju stringa ili na originalni string, ne mozes ga menjati), jedini problem moze da bude ako je referenca na instancu neke druge klase...
Dakle ako uradis objekatB = objekatA.Clone() to je kopija sa svojim vrednostima.
Code:
Public Class Igrac
Public ime As String
Public visina As Decimal
Public pozicija As Short
Public Ekipa As KosarkaskaEkipa
Sub New()
ime = ""
visina = 0
pozicija = 1
Ekipa = New KosarkaskaEkipa()
End Sub
Public Function Clone() As Object
Return MyBase.MemberwiseClone
End Function
End Class
Public Class KosarkaskaEkipa
Public Ime As String
Sub New()
Ime = ""
End Sub
End Class
....
Dim igracA As New Igrac
igracA.ime = "Pavle"
igracA.Ekipa.Ime = "Sampion"
Dim igracB As New Igrac
igracB = igracA.Clone()
igracB.ime = "Brane"
.......
... u ovoj situaciji igracA i igracB su dva različita objekta, i imaju referencu na isti objekat Ekipa, tako da kad promjenimo igracB.Ekipa.Ime ="LAL" tada će biti i igracB.Ekipa.Ime ="LAL" jer je to referenca na isti objekat.
Kako riješiti to da svaki od njih ima svoju instancu klase KosarkaskaEkipa, pošto nisam upoznat sa (de)Serijalizacijom, možete li mi dati jednostavan primjer Serijalizacije/deSerijalizacije?
Koja je to klasa u vb.net?
[ Majestic @ 17.08.2010. 12:44 ] @
Kada sam bolje pogledao tvoj problem, tebi treba
Factory pattern.
[ Shadowed @ 17.08.2010. 18:46 ] @
Citat: mmix: Iskreno, ja vise preferiram (de)serijalizaciju ako je potreban deep copy sa referencama, sporije je dosta, ali sam 100% siguran da nigde nije zalutala dupla referenca :)
Osim ako imas neki tip koji nece da se serializuje (kao Font na primer) pa onda moras i custom serijalizaciju..
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|