27. august 2010 - 15:49Der er
29 kommentarer og 1 løsning
Static vs accessor/mutator
Hej,
Hvis man nu har en class "MySuperClass" og en række subclasses "MySubClass1" "MySubClass2" ... "MySubClassN". Derudover haves en "PrimaryClass" som opretter x antal objekter af de forskellige subclasses til MySuperClass. Disse subclasses skal så tilgå samme information, fx en score.
Hvordan vil det mest hensigtsmæssigt laves?
Løsning 1: Lav en static instansvariabel i "MySuperClass" der indeholder den delte information. Alle subclasses kan herved læse/opdatere. (Bemærk ingen brug af tråde, så burde ikke være interferens problemer).
Løsning 2: Lav private instansvariabel i PrimaryClass, og en tilhørende accessor og mutator method. Ved oprettelse af objekter af de forskellige subclasses til MySuperClass fra PrimaryClass, sendes en reference (via "this") til PrimaryClass. Via denne reference kan subclasses så bruger get/set method til at tilgå den delte information.
Umiddelbar er løsning 1 jo langt den simpleste, men jeg mener at have hørt at man oftest gerne vil undgå brug af static da man mister fordele fra OOP.
1. Hvilken løsning er at foretrække, og hvorfor? 2. Hvornår vil man gerne undgå static? At dele informationer via static er vel først problematisk når objekter fra forskellige tråde skal tilgå informationen?
klasser != instanser Nej, hvor mener du da jeg siger det?
Altså jeg mener, jeg kan jo i superklassen lave en statisk variabel, og dermed tilgå denne fra subklasserne. Således vil alle instanser heraf kunne tilgå samme information. Ellers, kunne jeg i en særskilt klasse (Primary) oprette en privat instansvariabel, og sende en reference med når jeg fra Primary opretter instanser af andre selvstændige klasser. Dermed kan de tilgå fælles information via set/get metoder i Primary klassen. Derved undgås brug af statiske variabler.
Bemærk Primary er selvstændig, og ikke sub/superklasse til nogen af de andre klasser.
1.Kan du uddybe mere hvorfor det er bedre? Hvad er det dårlige ved at bruge en statisk variabel? 2.Hvorfor skulle det ikke give mening ved flere instanser/objekter af hver klasse?
Du har grundliggende en model hvor en instans af en "holder klasse" refererer til M instanser af subklasser til en bestemt klasse.
Saa laengde der kun er 1 instans af "holder klassen", saa vil det at gemme noget static passe med modellen, men faar du mere end en instans af den, saa giver static en anden funktionalitet.
Jeg tror saa at det vil vaere paenere at have en separat klasse X til data og have en ref til den i "holder klasse" instansen og sende den med over til instanserne af subklasserne fremfor at sende en ref til instansen af "holder klassen" selv med over.
public class WrongWay { public static void main(String[] args) { WWHolder a = new WWHolder("AAA"); System.out.println("AAA:"); a.print(); WWHolder b = new WWHolder("BBB"); System.out.println("BBB:"); b.print(); System.out.println("AAA again:"); a.print(); } }
class WWHolder { public static String magic; private List<WWP> lst; public WWHolder(String s) { magic = s; lst = new ArrayList<WWP>(); lst.add(new WWC1()); lst.add(new WWC2()); } public void print() { for(WWP o : lst) { o.print(); } } }
abstract class WWP { public abstract void print(); }
class WWC1 extends WWP { @Override public void print() { System.out.println("I am a C1 in " + WWHolder.magic); } }
class WWC2 extends WWP { @Override public void print() { System.out.println("I am a C2 in " + WWHolder.magic); } }
public class RightWay { public static void main(String[] args) { RWHolder a = new RWHolder("AAA"); System.out.println("AAA:"); a.print(); RWHolder b = new RWHolder("BBB"); System.out.println("BBB:"); b.print(); System.out.println("AAA again:"); a.print(); } }
class RWHolder { private String magic; private List<RWP> lst; public RWHolder(String s) { magic = s; lst = new ArrayList<RWP>(); lst.add(new RWC1(this)); lst.add(new RWC2(this)); } public void print() { for(RWP o : lst) { o.print(); } } public String getMagic() { return magic; } }
abstract class RWP { public abstract void print(); }
class RWC1 extends RWP { private RWHolder h; public RWC1(RWHolder h) { this.h = h; } @Override public void print() { System.out.println("I am a C1 in " + h.getMagic()); } }
class RWC2 extends RWP { private RWHolder h; public RWC2(RWHolder h) { this.h = h; } @Override public void print() { System.out.println("I am a C2 in " + h.getMagic()); } }
Jeg kan godt se din pointe, men i det tilfælde jeg bruger det kan jeg ikke helt se ulempen.
Prøver lige at forklare det lidt mere, inden jeg evt. skriver koden (hvis du vil have den, så sig til).
Altså, vi har en World, som opretter flere instanser af Player. Player er en subclass af Actor, og indeholder en statisk variabel static int team1Score, team2Score. Når en Player scorer, opdateres scoren ved dens tilhørende team ved at bruge den statiske varibel i superklassen. Når spillet er ovre kan scoren aflæses.
Her er jo ikke tale om kald fra World der opdaterer den statiske variabel, og situationer som den du demonstrerede vil jo ikke finde sted. Er der noget galt i her at anvende en statisk variabel? I så fald hvorfor?
PS: Det er vel korrekt at en statisk variabel der skal bruges i subklassen skal være protected ?
Ikke lige det bedste kodeeksempel, men prøv at se på dette:
[code] public class MyTest { public static void main(String[] args) { MySubClass player1 = new MySubClass(1); MySubClass player2 = new MySubClass(1); MySubClass player3 = new MySubClass(2); MySubClass player4 = new MySubClass(2);
1. MySubClass er der subklasse til MySuperClass. class MySubClass extends MySuperClass {...}
2. Nej korrekt, hvis man oprettede flere kampe på en gang, ville det gå galt. Men så længe det ikke er meningen er der så noget galt? Der er selvfølgelig det galt at man mister muligheden for flere kampe, hvilket vel netop er den stærke side ved at anvende OOP...
3. Egentlig kan man vel også sige at det er forkert at lade superklassen for players holde styr på scoren? I hvert fald ved denne struktor [code] MainClass ----- > Games Players /_\ /_\ /_\ | | | | | | Game ------- > PlayerType1 | \------------------------ > PlayerType2 [/code] Det er jo ikke Players der skal holde styr på scoren i spillet, men vel den enkelte Game-instans? Derfor bør de enkelte playere vel kalde en metode i Game (via reference sendt via constructor), som opdaterer en score gemt i Game? Ved ikke om det er forståeligt?
Nej præcis. Nu er dette en eksempel-øvelsesopgave, og derfor er det ikke meningen det skal kunne mere, men ja i den virkelige verden - på længere sigt - vil det jo ikke holde. Skal jo netop sørge for fleksibiliteten..
Ja, præcis. Som i ovenstående eksempel vel i Game klassen, da man kan forestille sig flere forskellige subclasses af Games (Forskellige spil). I Player giver det i hvert fald næppe mening.
(5) Dog hvis der er tale om spil hvor hver spiller bidrager med en score, så kunne man vel også gemme en lokal score i hver spiller, og hente denne score fra Game klassen, og eksempelvis addere resultatet. Men (4) er vel stadig en væsentlig mere fleksibel løsning?
Ja, så du vil altså: 1. have scoren som en private variabel i Kamp-klassen 2. Give reference til "this" med når Player's oprettes fra Kamp-klassen (altså sende reference til kampklassen med som argument ved kald af constructor) 3. Når score skal opdateres, kalde en mutator metode i Kamp-klassen vha. referencen til Kamp-klassen. ala enInstansAfKamp.score(enInstansAfPlayer);
Har jeg forstået dig rigtigt? Vil du mene det er den optimale løsning? Ligeledes metoder som end-game osv. skal vel styres af Kamp-klassen..?
PS: HVIS (hvilket jeg ikke længere har tænkt mig) man bruger statiske variabler til dette, er det så ikke korrekt at en statisk variabel der skal bruges i subklassen skal være protected ? Private er jo for beskyttet, og public er vel for åben.
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.