15. april 2006 - 21:56Der er
9 kommentarer og 2 løsninger
OOP: omkring static
Hej sidder og forsøger at lave lidt korrekt OOP i C#, og hertil skal siges jeg er uddannet multimediedesigner, så det hele er selvlært og derfor noget "shit" jeg laver.. Nedenstående tekst er derfor min opfattelse og bedes venligst rettes hvis der er helt ged i det :)
Jeg er så stødt på static, så jeg kan køre nogle metoder fra en klasse uden at initialiserer den (skulle jeg mene)..
Jeg har så et lille spørgsmål (giver lige et eksempel)
Jeg har en krypterings klasse, hvor jeg i min construktor initialisere værdierne, keys, provider osv.
public EasyEncryptor()
og 2 metoder En til at krypterer og en til at dekrypterer..
public Decrypt(string stringToBeDecrypted) public Encrypt(string stringToBeEncrypted)
Når de ikke er "static" skal jeg først oprette et krypterings object og kan herefter benytte mitobject.Encrypt("test");. Men jeg syntes så bare det er lettere at lave dem alle static og blot køre s = EasyEncryptor.Decrypt();
Syntes det giver mere overskueligt kode, og selvfølgeligt kortere, ved at spare initialisering af objectet..
MEN.. hvad er ulemperne? eller er det korrekt at lave alle de metoder man ønsker at bruge fra forksellige klasser static?
og lige et side spørgsmål:
hvis jeg har en : protected string s = "test";
hvordan vil jeg så tilgå den i en static metode? Error: "Cannot access non-static field bla bla bla"
Er jeg fuldstændig lost?
Håber der er en venlig sjæl der lige gider bruge et par minutter, på forhånd tak.
Utility-metoder som dem i din EasyEncryptor giver det meget god mening at have som static. En tommelfingerregel er, at hvis du har variable du gerne vil bruge i flere metoder i klassen, eller beholde værdien af, skal din klasse være "almindelig" altså instantierbar.
Du kan få fat på din string således:
protected static string s = "test";
public static void WriteSting() { Console.WriteLine( s ); }
Jeg vil nu advare imod at bruge en statisk protected medlem. (Hvis det endeligt skulle være noget burde det vel være private). Desuden, skal man tænke sig om når man har statiske variable; overvej hvad der sker hvis man fx har en metode der retter i en statisk variable og den metode kaldes af fra to (eller flere) tråde ca samtidigt.
Til jokkejensen: Du skriver at instanser initialiseres med keys, providers mv. Så er der jo netop tilstand der skal holdes-- mao et argument for at lave det instansbaseret. Alternativt kan du have en helt tredie klasse der holder tilstanden og overføre det til de statiske metoder, men det virker noget mindre clean.
Statiske metoder bruges oftest, når man vil udføre en operation, som er "global" og ikke knyttet til et objekts data. Dvs., når du skriver at du initialiserer værdierne i constructor; så er det netop det objekts data som du har initialiseret, du ønsker at bruge. Du skal derfor bruge en instansmetode, altså oprette objektet først.
Statiske medlemmer er delt mellem alle objekter.
Med andre ord, hvis du har en klasse MyClass:
public class MyClass { private int i; // i er instansdata
public MyClass(int interesting_integer) { i = interesting_integer; }
public void DoStuff() { // her kan du gøre ting med i; fordi det er instansdata. }
public static void DoStuffStatic() { // her kan du _ikke_ gøre ting med i; fordi du ikke har et objekt af klassen, men blot en metode, der er delt mellem alle objekter. } }
Med en objektorienteret tankegang har man typisk en klasse, der modellerer et objekt af en eller anden art. Det objekt har tilknyttet nogle data, der beskriver objektet. I dit tilfælde modellerer din klasse, en krypteringalgoritme. Krypteringen kan udføres på flere forskellige måder (keys, algoritmer, hvad ved jeg). Et objekt af klassen får info om hvordan den skal udføre krypteringen udfra de data, det indeholder. Du kan så bruge instansmetoder på objektet og få udført kryptering på netop den måde (keys, algoritmer ....) som svarer til objektets data.
jeg tilslutter mig "brug af state" => "non static"
men problemet opstår som regel kun hvis man går igang med at skrive noget kode og så skal have klasser og static versus non static til at gå igennem compileren
hvis man starter med objektorienteret analyse og design, så får man laver en masse klasser med non static metoder og til sidst kan man så lave en klasse eller to til den kode som ikke passer ind i objekt modellen
dj_lucas >> jeg kan forstå på de 3 andre at static metoder helst kun skal bruges "sjældent" og kun hvis andet ikke er muligt :) - jeg har som du, oprettet database metoder statiske.. mine utillities ex (DB)GetDataTable, (DB)ExecuteNonQuery og (Server)forskellige indstillinger - oprettet alt i static, og efter jeg er kommet lidt længere, brugt det som en "nødløsning" hvis det andet ikke lige vil virke:) Men jeg vil forsøge som beskrevet af de andre 3 at undgå dette.
Tuxic> "og den metode kaldes af fra to (eller flere) tråde ca samtidigt." Hmmm legede lidt med det..
Og åbner samme side med 2 sessions samtidigt, vil den i Session 2, skrive 2.. Vil det sige at static variabler deles mellem sessions at det er en "global" værdi (fra driis)... (uden static skriver den 1 i begge Sessions)
Hvis jeg holdte mig til static, og skal vi sige tilfældigt gik de 10 forskellige Sessions ind og kaldte mit Decrypt kald samtidig, som jeg har planer om at bruge til at gemme cookies hos brugeren - hvad vil konsekvensen være? (samme pass til forskellige brugere ?, langsom performance ? eller ?) eller er der et andet eksempel der vil være mere illustativt - bruger det ex også til mine database kald.
Driis> som nævnt ovenstående bruger jeg også static til mine database kald, ex vil jeg have flere metoder der skal bruge flere database kald. Efter lidt undersøgelser har jeg så set man kan: (i page_load) DB test = new DB(); test.ExecuteNonQuery("Insert into sitetype(value) values ('test')"); test.ExecuteNonQuery("Insert into sitetype(value) values ('test2')");
Altså udføre 2 kald på samme object, jeg trode man skulle initialisere 2 database objecter for at udføre de 2 kald - hvorfra jeg har det ander jeg ikke :)
På hvor højt et niveau kan jeg kalde det database object, jeg har ex en nogenlunde opbygning som kendt fra abejdet, en række usercontrols, der arves af andre usercontrols, som ligger som placeholders omkring på default siden... kan jeg godt oprette et database object i Page_load på hver usercontrol og benytte dette til alle mine metoder i usercontrolen, eller initialiserer man godt nok et nyt i hver metode.
Jeg tænker rent performance mæssigt, jo flere database objecter jeg opretter, jo mere performance mister jeg. Måske maginaler - men mere teorien bag, så jeg kan få det lært. Eller ?
Arne_v> Forstår jeg dig ret.. designer man ikke med statiske metoder - men bruger dem til sidst til at samle funktionalitet der ellers ikke kan passe ind de oprettede klasser. Jeg må indrømme jeg ikke har siddet og "analyseret og designet" mit behov - Det virker totalt uoverskueligt for mig, at skulle skitsere alt det jeg får brug for, før jeg er gået i gang. Nok erfaringen der mangler..
Jeg tror det er fordi jeg har set det som hver gang jeg oprettede et object, ville det tage tid, og ved static metoder opretter jeg (i mine øjne) ikke objectet, men udfører blot en funktionalitet der udfører en ønsket handling, men der er altså ingen ulempe ved at initialiserer flere (ex) database objecter og benytte disse i samme klasse - ingen ulempe ved at initialisere objectet og bruge metoden bagefter, udover at at skrive den ekstra linie..
Den overordnede grund til ikke at bruge static, er vel så designet af systemet?
Jeg er ked af jeg ikke kan spytte flere points i, men deler gerne de nye "personlige" spørgsmål ud i nye tråde om nødvendigt, endnu engang tak !
Der er dog et problem ved at lave det statisk. Du kan ikke lave objekter af det, og derfor vil det kun være mulig at have én af disse, så du kan f.eks. ikke have flere krypterings objekter med forskellige nøgler, da de alle deres de samme varibler til at gemme disse i.
Jo, vi tager lige et eksempel: class Test { public static int Count; }
Hvis du skriver dette her i din main metode: Test t1 = new Test(); Test t2 = new Test(); t1.Count = 5; Console.WriteLine(t2.Count);
Hvis jeg ikke tager helt fejl, så vil det udskrive 5.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.