|
| Programmering med constructors og destruct~ Fra : JM |
Dato : 08-12-02 19:23 |
|
Kan nogen forklare mig, hvad årsagen er til, at constructors og destructors skal
være der - har det i det hele taget nogen betydning i pascal, om der står
constructor og destructor - og hvad er årsagen. Jeg er klar over, at det ikke
altid fungere uden nogen constructor og destructor - men jeg vil godt vide, om
at man ikke forholdsvis nemt kunne have lavet det, så der ikke var nogen
forskel, og hvad årsagen er til, at man ikke har gjort dette. Jeg syntes, at det
virker ulogisk, at det ikke er det samme, om det står en constructor, eller en
almindelig procedure.
| |
Toke Eskildsen (08-12-2002)
| Kommentar Fra : Toke Eskildsen |
Dato : 08-12-02 20:06 |
|
In article <1103_1039371763@news.sunsite.dk>, ccc41290@vip.cybercity.dk
says...
> Kan nogen forklare mig, hvad årsagen er til, at constructors
> og destructors skal være der
Constructors fordi det er smart at have en procedure, der altid bliver
kaldt, når man opretter et objekt. Hvis man ikke bruger en constructor,
bliver det meget hurtigt noget rod at huske på om man skal kalde en
initialiseringsmetode eller ej, når man skal bruge et objekt.
Compileren giver en fejl, hvis man ikke kalder en constructor når man
vil oprette et objekt. Alternativt ville en forglemmelse først blive
fanget på runtime.
Destructors er smarte af ca. samme årsag. Pascal benytter ikke garbage
collection, så det er igen en stor hjælp at man ikke eksplicit skal
huke at kalde en eller anden oprydningsrutine, hver gang man er færdig
med at bruge et objekt.
Det gør det også muligt at lave generiske containere med objekter:
Containeren ved at den altid kan kalde Free på et objekt, for at
frigive objektet og derigennem objektets eventuelle underobjekter.
--
Toke Eskildsen <URL: http://ww.daimi.au.dk/~darkwing/>
| |
Toke Eskildsen (08-12-2002)
| Kommentar Fra : Toke Eskildsen |
Dato : 08-12-02 20:20 |
|
In article <MPG.185db62b3fab900e989695@News.CIS.DFN.DE>,
dakwing@daimi.au.dk says...
> Destructors er smarte af ca. samme årsag. Pascal benytter ikke garbage
> collection, så det er igen en stor hjælp at man ikke eksplicit skal
> huke at kalde en eller anden oprydningsrutine, hver gang man er færdig
> med at bruge et objekt.
Dumt formuleret: Man skal netop eksplicit huske at kalde
oprydningsrutinen. Det smarte er så at man ved en destructor ved
hvilken det er.
--
Toke Eskildsen <URL: http://ww.daimi.au.dk/~darkwing/>
| |
JM (08-12-2002)
| Kommentar Fra : JM |
Dato : 08-12-02 21:24 |
|
> Dumt formuleret: Man skal netop eksplicit huske at kalde
> oprydningsrutinen. Det smarte er så at man ved en destructor ved
> hvilken det er.
Lyder fornuftigt - som ved constructoren.
| |
JM (08-12-2002)
| Kommentar Fra : JM |
Dato : 08-12-02 21:17 |
|
Sun, 8 Dec 2002 20:05:50 +0100, Toke Eskildsen <dakwing@daimi.au.dk> skrev:
> In article <1103_1039371763@news.sunsite.dk>, ccc41290@vip.cybercity.dk
> says...
> > Kan nogen forklare mig, hvad årsagen er til, at constructors
> > og destructors skal være der
>
> Constructors fordi det er smart at have en procedure, der altid bliver
> kaldt, når man opretter et objekt. Hvis man ikke bruger en constructor,
> bliver det meget hurtigt noget rod at huske på om man skal kalde en
> initialiseringsmetode eller ej, når man skal bruge et objekt.
Det kan det være noget om, når at de ikke kaldes automatisk.
Men spørgsmålet er egentlig også lidt i retning af, om at constructor ordet
egentlig gør noget - eller om det "bare" er en slags "kommentar".
>
> Compileren giver en fejl, hvis man ikke kalder en constructor når man
> vil oprette et objekt. Alternativt ville en forglemmelse først blive
> fanget på runtime.
Hvem siger, at det er en forglemmelse hvis at det ingen er? Det kunne jo ske, at
man simpelthen ikke havde noget i den, og så syntes at det var frås af kald.
F.eks. hvis at man har et array, af en hel masse elementer, så vil det måske
være uden grund at skulle kalde en tom constructor.
Constructors uden noget i, burde man jo kunne lade være med at kalde. Det at
kalde en tom procedure er jo det rene vås - specielt når hastigheden går ned.
Dog må jeg give dig ret i, at når man ikke kan "huske" så kan det være rimeligt
at have idiotregler, som kald altid en constructor.
Jeg havde nok foretrækket, hvis at man ikke behøvede at have hverken
constructors eller destructors, så de ikke optog tid og plads. For ofte, så er
de jo reelt uden noget i. Og så kunne man så proppe dem ind, hvis at man vil
have at de skulle kaldes, og ellers kunne den spare hele den automatiske kald
bort ved compileringen. Til gengæld, vil det så kun være logisk, hvis at de
kaldes automatisk, og ikke som nu manuelt, da det så er noget om, at det jo nok
er nemmest at altid kalde en constructor manuelt fordi at man jo ellers skal til
at ændre alt, så snart at constructors tilføjes. Men man må kunne spare en masse
kode, hvis man undgår alle disse unødige kald, ved at kun have constructors og
destructors med noget i - da at det jo er totalt ligegyldigt med procedurer uden
indhold. Og så bliver compileren fri for at kalde dem.
Umiddelbart, så tror jeg, at det er en god idé, at lade være med at have
constructors, og destructors. Men desvære, så virker det ikke altid - og
det syntes jeg er totalt uden grund.
>
>
> Destructors er smarte af ca. samme årsag. Pascal benytter ikke garbage
> collection, så det er igen en stor hjælp at man ikke eksplicit skal
> huske at kalde en eller anden oprydningsrutine, hver gang man er færdig
> med at bruge et objekt.
Hvis at jeg fjerner en klasse med dispose, og så ikke har nogen destructor - er
det så et problem, og hvorfor er det? Umiddelbart mener jeg, at destructers ikke
kan have noget at sige, hvis at de ikke f.eks. fjerner et element i en linket
liste, hvor at man så til gengæld vil have en constructor til at sætte elementet
på listen, og en destructor til at tage den af - og så bruge en dobbeltkædet
liste. Altså, i mange tilfælde burde det da hverken være constructors og
destructors, og de kan være totalt tomme - og alligevel så bliver man tvunget
til at ligge dem der, hvis at compileren ellers nægter at oversætte eller udføre
tingene. Hvorfor gør den dog dette?
>
> Det gør det også muligt at lave generiske containere med objekter:
> Containeren ved at den altid kan kalde Free på et objekt, for at
> frigive objektet og derigennem objektets eventuelle underobjekter.
Hvis det overhovedet ikke er nogen destructors og constructors, for hverken
objekter eller underobjekter, så burde det ikke være noget problem. (altså
forudsat at det ikke er nogen grund til det)
Og umiddelbart, så virker det jo også logisk, at den bare kalde den
underliggende destructor - eller de underliggende - hvis at det ikke er nogen i
et objekt. Hvis at det er en procedure, som jeg har - og så forsøger at kalde
denne, så vil den jo også findes, fordi den arves. Og dermed, så vil den også
kalde destructoren, fordi at disse altid arves som procedurer. En destructor vil
måske blokere de underliggende - dette har jeg endnu ikke prøvet. Så må man jo
så kunne kalde den, ved at kalde den "forrige" destructor, ved at kalde destruct
i destructoren, så den kalder forrige gyldige.
Så jeg ser ikke problem.
> --
> Toke Eskildsen <URL: http://ww.daimi.au.dk/~darkwing/>
| |
Toke Eskildsen (08-12-2002)
| Kommentar Fra : Toke Eskildsen |
Dato : 08-12-02 22:20 |
|
In article <1106_1039378596@news.tele.dk>, ccc41290@vip.cybercity.dk
says...
> Men spørgsmålet er egentlig også lidt i retning af, om at
> constructor ordet egentlig gør noget - eller om det "bare"
> er en slags "kommentar".
Den fortæller compileren at der skal returneres en reference til det
nyoprettede objekt. Man kunne tænke sig en alternativ konstruktion:
function TWhatever.myPersonalConstructor: TWhatever
Jeg ser ikke problemet i at benytte et ord til at beskrive hvilke
metoder der er constructors. Jeg ved at Java f.eks. har valgt at
markere constructors ved at lave en metode med samme navn som klassen,
men forskellen er bare syntaktisk.
Toke:
> > Compileren giver en fejl, hvis man ikke kalder en constructor
> > når man vil oprette et objekt. Alternativt ville en forglemmelse
> > først blive fanget på runtime.
> Hvem siger, at det er en forglemmelse hvis at det ingen er? Det
> kunne jo ske, at man simpelthen ikke havde noget i den, og så
> syntes at det var frås af kald.
Hellere nogle spildte tegn end en altid tilstedeværende sandsynlighed
for at glemme at kalde initialisering på objektet.
> Constructors uden noget i, burde man jo kunne lade være med at
> kalde. Det at kalde en tom procedure er jo det rene vås -
> specielt når hastigheden går ned.
Hastigheden afhænger af compileren. Hvis den bare er moderat smart,
genererer den ingen ekstra kode for tomme constructors.
> Dog må jeg give dig ret i, at når man ikke kan "huske" så kan det
> være rimeligt at have idiotregler, som kald altid en constructor.
Er det også "idiotregler" at have f.eks. typecheck? Det virker som om
du opfatter constructors som støttehjul til mindrebemidlede. I så
tilfælde vil jeg anbefale et sprog som c, der gør det meget nemt at
lave fejl med pointers og hukommelsesallokering. Ingen støttehjul der.
> For ofte, så er de jo reelt uden noget i.
Det kommer så sandelig an på hvad du laver. Jeg har den omvendte
erfaring.
> Men man må kunne spare en masse kode, hvis man undgår alle disse
> unødige kald, ved at kun have constructors og destructors med
> noget i - da at det jo er totalt ligegyldigt med procedurer uden
> indhold. Og så bliver compileren fri for at kalde dem.
Nu ved jeg ikke hvilken variant af Pascal du bruger. Jeg bruger Delphi
og der er det ikke nødvendigt at lave en constructor, hvis du ikke har
noget at fylde i den.
Du skal dog stadig kalde constructoren ved objektoprettelse. Det
betyder så bare at den kalder constructoren for superklassen.
Syntaktisk er vi nødt til at fortælle compileren at vi vil oprette et
objekt. Om det gøres med TMyClass.Create, new TMyClass(), Create
(TMyClass), &TMyClass eller en femte måde, ser jeg ikke den store
forskel på. Hvis man valgte f.eks. &TMyClass, kunne man spare 6 tegn i
forhold til TMyClass.Create. Er det "en masse kode"?
> Umiddelbart, så tror jeg, at det er en god idé, at lade være med at
> have constructors, og destructors.
Efter erfaring med sprog med & uden constructors, mener jeg de er en
fin ting[1].
> Hvis at jeg fjerner en klasse med dispose, og så ikke har nogen
> destructor - er det så et problem, og hvorfor er det?
Hvis det objekt du fjerner selv har allokeret flere objekter, vil
manglen på en destructor-metode betyde at disse objekter flyder frit i
hukommelsen.
> Og umiddelbart, så virker det jo også logisk, at den bare kalde den
> underliggende destructor - eller de underliggende - hvis at det ikke
> er nogen i et objekt
Korrekt. Det gør Delphi også.
> Så jeg ser ikke problem.
Det ser ud til at det du protesterer mod er at skrive tomme
constructors og destructors. Det lyder som en svaghed ved den variant
af Pascal du anvender.
[1] Ikke nødvendigvis ordet "constructor", men i stedet det at have
initialiseringsmetoder, man _ved_ bliver kaldt, når man opretter
objekter.
--
Toke Eskildsen <URL: http://ww.daimi.au.dk/~darkwing/>
| |
René Jensen (08-12-2002)
| Kommentar Fra : René Jensen |
Dato : 08-12-02 23:53 |
|
JM wrote:
> Men spørgsmålet er egentlig også lidt i retning af, om at constructor ordet
> egentlig gør noget - eller om det "bare" er en slags "kommentar".
Ordet 'constructor' er et reserveret ord, som fortæller Delphi/Pascal
compileren at nedenstående kode er et objekts constructor-procedure.
> Hvem siger, at det er en forglemmelse hvis at det ingen er?
Det gør jeg bl.a., for du kan *ikke* have et objekt uden en constructor
og destructor; at du så ikke behøves at skrive en, skyldes at Delphi
compileren selv kan finde ud af have en tom constructor/destructor.
> F.eks. hvis at man har et array, af en hel masse elementer, så vil det måske
> være uden grund at skulle kalde en tom constructor.
Det gør du heller ikke, da en instans af array ikke er et objekt.
> Umiddelbart, så tror jeg, at det er en god idé, at lade være med at have
> constructors, og destructors. Men desvære, så virker det ikke altid - og
> det syntes jeg er totalt uden grund.
Så har du misforstået noget omkring generelt OOP.
> Hvis at jeg fjerner en klasse med dispose, og så ikke har nogen destructor - er
> det så et problem, og hvorfor er det? Umiddelbart mener jeg, at destructers ikke
> kan have noget at sige, hvis at de ikke f.eks. fjerner et element i en linket
> liste, hvor at man så til gengæld vil have en constructor til at sætte elementet
> på listen, og en destructor til at tage den af - og så bruge en dobbeltkædet
> liste. Altså, i mange tilfælde burde det da hverken være constructors og
> destructors, og de kan være totalt tomme - og alligevel så bliver man tvunget
> til at ligge dem der, hvis at compileren ellers nægter at oversætte eller udføre
> tingene. Hvorfor gør den dog dette?
For det første så fjerner du ikke en klasse med dispose, det gøres vha.
free-metoden, som igen kalder terminate-metoden (så vidt jeg husker).
Grunden til at du har en destructor, er at du skal huske at fjerne de
ting, som du har allokeret i hukommelsen, ellers vil dit program blive
ved med at allokkere hukommelse, hver gang en bruger starter en ny
instans af dit program. -F.eks. hvis dit objekt benytter andre objekter.
Igen du har misforstået noget om OOP. En constructor og en destructor
kaldes *kun* en gang for hver objekt, som bliver oprettet. I dit
eksempel med hægtede lister, vil du altså ikke kunne bruge constructor
og desctructoren til at tilføje og slette elementer fra listen, da du så
kun vil kunne tilføje et link og fjerne samme link igen; og det var ikke
meningen med hægtede lister. Derfor benytter man to metoder, som
henholdsvis tilføjer og sletter elementer fra listen.
> Hvis det overhovedet ikke er nogen destructors og constructors, for hverken
> objekter eller underobjekter, så burde det ikke være noget problem. (altså
> forudsat at det ikke er nogen grund til det)
>
> Og umiddelbart, så virker det jo også logisk, at den bare kalde den
> underliggende destructor - eller de underliggende - hvis at det ikke er nogen i
> et objekt. Hvis at det er en procedure, som jeg har - og så forsøger at kalde
> denne, så vil den jo også findes, fordi den arves. Og dermed, så vil den også
> kalde destructoren, fordi at disse altid arves som procedurer. En destructor vil
> måske blokere de underliggende - dette har jeg endnu ikke prøvet. Så må man jo
> så kunne kalde den, ved at kalde den "forrige" destructor, ved at kalde destruct
> i destructoren, så den kalder forrige gyldige.
>
> Så jeg ser ikke problem.
Men der er et problem! -Det er noget værre rod at kalde free for et
objekt, som hierarkisk ligger over et andet objekt. Da objekter kan
nedarve egenskaber fra et parent objekt, og derfor kan et forældre
objekt ikke vide hvad der ligger i et child objekt; da man her taler om
generalisering og specialisering, som er to vidt forskellige ting i OOP.
Ved at kalde et objekts free-metode, som er mest specialiseret og derved
kalde free-metoden for det næstemest specialiseret objekt osv. sørger du
for at deallokere korrekt. Det er sådan set det der bliver gjort, selvom
et givet objekts descructor er tom.
Med venlig hilsen,
René Jensen
| |
dyekjaer (09-12-2002)
| Kommentar Fra : dyekjaer |
Dato : 09-12-02 03:55 |
|
I må undskylde, hvis at jeg svarer, eller skriver flerer gange. Men jeg
har problem for øjeblikket og er ikke sikker på om noget fungerer.
Sun, 08 Dec 2002 23:53:03 +0100, René Jensen <not4u2know@privacy.org>
skrev:
> > Hvem siger, at det er en forglemmelse hvis at det ingen er?
>
> Det gør jeg bl.a., for du kan *ikke* have et objekt uden en
constructor
> og destructor; at du så ikke behøves at skrive en, skyldes at Delphi
> compileren selv kan finde ud af have en tom constructor/destructor.
Det er også dette, at jeg har fundet ud af sker. Men det er jo ikke
nogen
grund til det. Så vidt jeg kan se, så initialiserer den "bare" et felt
som
hedder VMT - og dette felt burde da ikke behøve at blive initialiseret,
da
det er overflødigt.
>
> > F.eks. hvis at man har et array, af en hel masse elementer, så vil
det måske
> > være uden grund at skulle kalde en tom constructor.
>
> Det gør du heller ikke, da en instans af array ikke er et objekt.
Det var nu modsat, at dette var tænkt: var test:array[0..1000] of
blabladobject;
Denne vil kalde constructoren 1001 gange og bare gå ud. Det er da
snævlekode når
det er compileret.
Mon ikke, at det rigtige er, at det kun skyldes en ældre udgave af
Delphi
eller evt en gammel OOP turbopascal 7. Med ny udgave, tror jeg også
gerne, at intet kode var kaldt for objektet, også med klasser og
virtual functioner i dem.
>
> > Umiddelbart, så tror jeg, at det er en god idé, at lade være med at
have
> > constructors, og destructors. Men desvære, så virker det ikke altid
- og
> > det syntes jeg er totalt uden grund.
>
> Så har du misforstået noget omkring generelt OOP.
>
Hi. Jeg vil bare have dem til at lave det, så den elendige VMT felt skal
væk, og
ikke give gevoldigheder. Men jeg har forstået, at det kun er min pokkers
elendige gamle version (7.0), som har fejlen. Og ikke kan optimere
ordentlig
væk, så det forsvinder totalt, når at constructoren er uden noget i.
> For det første så fjerner du ikke en klasse med dispose, det gøres
vha.
> free-metoden, som igen kalder terminate-metoden (så vidt jeg husker).
> Grunden til at du har en destructor, er at du skal huske at fjerne de
> ting, som du har allokeret i hukommelsen, ellers vil dit program blive
> ved med at allokkere hukommelse, hver gang en bruger starter en ny
> instans af dit program. -F.eks. hvis dit objekt benytter andre
objekter.
Du skal jo bare sætte parameter på dispose, så kalder du din destructor!
Ligesom freemem..
>
> Igen du har misforstået noget om OOP. En constructor og en destructor
> kaldes *kun* en gang for hver objekt, som bliver oprettet. I dit
> eksempel med hægtede lister, vil du altså ikke kunne bruge constructor
> og desctructoren til at tilføje og slette elementer fra listen, da du
så
> kun vil kunne tilføje et link og fjerne samme link igen; og det var
ikke
> meningen med hægtede lister. Derfor benytter man to metoder, som
> henholdsvis tilføjer og sletter elementer fra listen.
Intet problem. Det har altid fungeret.
Mit objekt virker, så at når klassen creeres, så sættes den automatisk
ind
på en dobbeltkædet liste, og når den fjernes, så tages den ud af listen.
På
den måde, så laver man dobbeltkædede klasser - og det fungerer fornemt.
Og
den oprettes, og nedlukkes automatisk, og listen trådes automatisk
korrekt.
Hvad skulle man ellers bruge "destructors" til??? Og også constructors.
>
> Men der er et problem! -Det er noget værre rod at kalde free for et
> objekt, som hierarkisk ligger over et andet objekt. Da objekter kan
> nedarve egenskaber fra et parent objekt, og derfor kan et forældre
> objekt ikke vide hvad der ligger i et child objekt; da man her taler
om
> generalisering og specialisering, som er to vidt forskellige ting i
OOP.
Hvis man syntes at OOP er noget rod, så er det først fordi at man aldrig
har
forstået det... Nåh. Spøj til side. Naturligvis er det rod.
>
> Ved at kalde et objekts free-metode, som er mest specialiseret og
derved
> kalde free-metoden for det næstemest specialiseret objekt osv. sørger
du
> for at deallokere korrekt. Det er sådan set det der bliver gjort,
selvom
> et givet objekts descructor er tom.
Det ovenstående lyder meget teknisk. Det er jo nok sådan, at det hedder
idag.
Jeg plejer at specialisere mine ting efter funktion. Og hoved.
>
> Med venlig hilsen,
> René Jensen
--
Leveret af:
http://www.kandu.dk/
"Vejen til en hurtig løsning"
| |
dyekjaer (09-12-2002)
| Kommentar Fra : dyekjaer |
Dato : 09-12-02 04:36 |
|
> Det var nu modsat, at dette var tænkt: var test:array[0..1000] of
> blabladobject; Denne vil kalde constructoren 1001 gange og bare gå ud.
> Det er da snævlekode når det er compileret.
Man skal selv kalde constructoren, men det skal forstås sådan, at uden
den
kaldes, så er det problem med at objektet ikke fungerer korrekt, da
denne oftest
anvender virtual procedures og disse ikke vil fungere uden VMT feltet er
initialiseret, af constructoren, hvilket jo er en fejl i compileren.
Masser af procedurekald, osv. for at få ovenstående til at fungere. Bare
for at kalde en total
tom constructor uden nogen new og freemem og andet i. Det må være en
fejl, i min udgave af TP7, at det kræves.
Umiddelbart så må det jo nok være løst i de nye, hvor at alt optimeres
godt.
--
Leveret af:
http://www.kandu.dk/
"Vejen til en hurtig løsning"
| |
dyekjaer (09-12-2002)
| Kommentar Fra : dyekjaer |
Dato : 09-12-02 04:12 |
|
> Det var nu modsat, at dette var tænkt: var test:array[0..1000] of
> blabladobject; Denne vil kalde constructoren 1001 gange og bare gå ud.
> Det er da snævlekode når det er compileret.
Naturligvis skal man selv kalde constructoren, men det skal forstås
sådan, at
uden den kaldes, så er det problem med at objektet ikke fungerer
korrekt, da
denne oftest anvender virtual procedures og disse ikke kan fungere. Jeg
tror,
at det kun er fordi at jeg har en sådan gammel udgave, at det er den
store fejl,
og at den ikke kan finde ud af, at optimere korrekt, og evt. også fjerne
enhver
kald, når at der ikke er noget i min constructor.
--
Leveret af:
http://www.kandu.dk/
"Vejen til en hurtig løsning"
| |
|
|