Avatar billede appel Novice
17. februar 2003 - 18:12 Der er 29 kommentarer og
1 løsning

interfaces, overloading og måske patterns...

Problem:

Har to instanser a og b af henholdsvis klasserne A og B.
Disse instanser bliver gemt i en Vector v.
Yderligere opretter jeg en ny instans aa af klassen A.
I klassen A skal der være en metode "printObject" der via overloading tager en instans af A eller B som input, og kan printe to forskellige strenge ud alt afhængig af input typen.

Dvs:

public class test{
    static Vector v;
    public static void main(String[] args) {
        A a = new A();
        A aa = new A();
        B b = new B();
   
        v.addElement(a);
        v.addElement(b);

        ... her kan der tilføjes kode       


        aa.printObject(v.Element(0));
        aa.printObject(v.Element(1));


Højst sandsynligt kan det løses med et smart interface og ved at tilføje en metode til både A og B, men jeg er desværre kørt fast og kunne godt bruge noget inspiration... Hvad siger i ?
Avatar billede arne_v Ekspert
17. februar 2003 - 18:20 #1
public interface AB {
    void printObject();
}

public class A implements AB {
    void printObject() {
        // print
    }
}

public class B implements AB {
    void printObject() {
        // print
    }
}

  A a = new A();
  B b = new B();
  v.addElement(a);
  v.addElement(b);

  ((AB)v.get(i)).printObject();

er den objektorienterede måde at gøre det på !
Avatar billede arne_v Ekspert
17. februar 2003 - 18:24 #2
Det er langt det pæneste at objekterne selv ved hvordan de skal udskrives
fremfor at en anden klasse skal kunen gøre det.
Avatar billede appel Novice
17. februar 2003 - 18:26 #3
Problemet er at der skal være to forskellige PrintObject for hver klasse A og B. Dvs

public class A implements AB {
    void printObject(A a) {
        // print
    }
    void printObject(B b) {
        // print
    }
}
Avatar billede appel Novice
17. februar 2003 - 18:28 #4
Ja ok. Men printObject er også bare et navn jeg har fundet på... I virkeligheden skulle det måske heller have heddet "act", da metoden bestemmer hvordan et objekt skal opføre sig når det "møder" et andet objekt ...
Avatar billede arne_v Ekspert
17. februar 2003 - 18:29 #5
Der er også 2 printObject i mit koncept - forskellen er
at A ved hvordan man printer en A og B ved hvordan man printer en B.
Avatar billede appel Novice
17. februar 2003 - 18:29 #6
Det vil altså sige:

public class A implements AB {
    void act(A a) {
        // A møder et objekt af typen A og gør noget
    }
    void act(B b) {
        // A møder et objekt af typen B og gør noget
    }
}
Avatar billede arne_v Ekspert
17. februar 2003 - 18:29 #7
I.s.f. at ved det om både A og B.
Avatar billede appel Novice
17. februar 2003 - 18:30 #8
og:

public class B implements AB {
    void act(A a) {
        // B møder et objekt af typen A og gør noget
    }
    void act(B b) {
        // B møder et objekt af typen B og gør noget
    }
}
Avatar billede arne_v Ekspert
17. februar 2003 - 18:31 #9
Nej - det løser ikke dit problem og det er ikke særligt kønt
da A så skal vide en masse om B.
Avatar billede appel Novice
17. februar 2003 - 18:33 #10
Problemet var også om der eksisterede en elegant måde at løse problemet på ?
Avatar billede arne_v Ekspert
17. februar 2003 - 18:34 #11
Hvis det er en A og B som skal "interacte" med hinanden, så vil jeg nok snarere
foreslå nget i retning af:

public abstract class AB {
    void act(AB ab) {
        // do whatever
    }
    public abstract String me();
}

public class A extends AB {
    public String me() {
        return "I am a A";
    }
}

public class B extends AB {
    public String me() {
        return "I am a B";
    }
}
Avatar billede arne_v Ekspert
17. februar 2003 - 18:35 #12
Og så:

  A a = new A();
  B b = new B();
  v.addElement(a);
  v.addElement(b);

  ((AB)v.get(i)).act((AB)v.get(i+1));
Avatar billede appel Novice
17. februar 2003 - 18:38 #13
de skal i og for sig ikke interacte.
Det eneste der så at sige skal ske er blot at der kaldes to forskellige metoder i den samme klasse, afhængig hvilken type objekt der bliver taget ud af vektoren ...
Avatar billede arne_v Ekspert
17. februar 2003 - 18:44 #14
Så er du tilbage ved instanceof og udenfor objektorienteret fremgangsmåde.

Java bruger compile time binding ikke runtime binding til
method overloading.

Den metode jeg har skitseret med et interface og en metode i
hver sin klasse er den rigtige måde at gøre det på.
Avatar billede =maddog= Nybegynder
17. februar 2003 - 18:45 #15
Man skal tænke sig om som bare p*kker når man laver et interface. Man kan ikke bare tilføje en ny metode, så man skal have rigtig meget styr på hvad man laver.
Hvad gør printObject til en start? Kunne det laves med en statisk metode evt. i A eller B klassen, og derved anvendes uden en instans (A.printObject())?
Avatar billede appel Novice
17. februar 2003 - 18:51 #16
>> arne_v

Problemet er bare det ikke løser mit problem :-)

>> arne_v og =maddog=

Jeg skal have en metode i hver klasse således objektet af den pågældende klasse agerer ud fra hvad der bliver hevet ud af vektoren. Hvert objekt der bliver taget ud af vektoren er en aktør som det pågældende objekt skal reagerer differentieret overfor.
Hvis det kan løses på anden måde er jeg også meget interesseret ...
Avatar billede arne_v Ekspert
17. februar 2003 - 18:52 #17
Hm.

Interfaces er meget brugt i både standard OOD/OOP og de fleste kendte
Java frameworks.
Avatar billede arne_v Ekspert
17. februar 2003 - 18:54 #18
Hvis ikke du vil bruge interface eller abstract class, så er du tilbage
ved instanceof og if statement.
Avatar billede appel Novice
17. februar 2003 - 18:56 #19
Jeps jeg er med på interfaces... Jeg mener også der skal laves et interface hvis man skal løse mit problem, problemet er bare at det konkrete interface du foreslog ikke løser mit problem.
Som du selv nævner kunne det jo let løses ved en masse if sætninger og instance of ... men det er jo ikke den elegante OO løsning... Der for dette indlæg.
Avatar billede arne_v Ekspert
17. februar 2003 - 19:04 #20
Hvad med:

public abstract classs AB {
    void act(AB ab) {
        ab.realAct();
    }
    public abstract void realAct();
}

public class A implements AB {
    public void realAct() {
        // something
    }
}

public class B implements AB {
    public void realAct() {
        // something
    }
}

  A a = new A();
  B b = new B();
  v.addElement(a);
  v.addElement(b);

  ((AB)v.get(i)).act((AB)v.get(i+1));

?
Avatar billede arne_v Ekspert
17. februar 2003 - 19:05 #21
Hovsa - det skal naturligvis være extends ikke implements:

public abstract classs AB {
    void act(AB ab) {
        ab.realAct();
    }
    public abstract void realAct();
}

public class A extends AB {
    public void realAct() {
        // something
    }
}

public class B extends AB {
    public void realAct() {
        // something
    }
}

  A a = new A();
  B b = new B();
  v.addElement(a);
  v.addElement(b);

  ((AB)v.get(i)).act((AB)v.get(i+1));
Avatar billede arne_v Ekspert
17. februar 2003 - 19:27 #22
Hvis du evt. fortalte lidt mere om A og B, så kunne vi måske få
nogle gode ideer til, hvordan du kunne strukturere dit klasse
hieraki, så du får en "pæn" løsning.

Det er lidt svært på det foreliggende grundlag.
Avatar billede appel Novice
17. februar 2003 - 19:50 #23
Det handler om at jeg skal simulere en predator prey situation, som foregår i en afgrænset verden (JFrame).

Forestil dig vi har en klasse der hedder Shark og en klasse der hedder Herring (sild). Vi antager således vi har flere objekter af klassen Shark og flere objekter af klassen Herring. For hvert objekt, altså sild eller haj, skal deres opførsel simuleres. Det vil sige hvis en sild befinder sig inde for en hvis afstand af en haj, vil hajen jagte silden. Hvis den derimod er tæt på en haj, kan det være den vil parre sig. Ideen er således at jeg vil gemme alle objekterne (fiskene og hajerne) i en Vector, for hver fisk er der også en position, således kan det afgøres hvilken en den aktuelle haj eller fisk først får øje på og agere efter. Det ville derfor være smart hvis både Shark og Herring klassen hver havde to forskellige implementationer af Act, en til hvis hajen så en sild og en hvis den så en anden haj og vice versa.

Det var så den lange forklaringe, håber det blev lidt mere klart ...
Avatar billede appel Novice
17. februar 2003 - 19:53 #24
rettelse: "Hvis den derimod er tæt på en haj, kan det være den vil parre sig"
-> "Hvis en haj derimod er tæt på en anden haj, kan det være den vil parre sig eller noget helt andet og har derfor en anden adfærd end hvis det var en sild den så."
Avatar billede arne_v Ekspert
17. februar 2003 - 20:07 #25
OK - jeg tror jeg forstår problem-stillingen og kan også se nogle
muligheder:

public abstract class Fish {
  private Position pos;
  public Position getPos() {
      return pos;
  }
  public void setPos(Position pos) {
      thos.pos = pos;
  }
  public abstract void meetOtherFish(Fish f);
  public abstract boolean isPredator();
}

public class Shark extends Fish {
  public void meetOtherFish(Fish f) {
      if(!f.isPredator()) {
          // forsøg at fange den
      } else (f instanceof Shark) {
          // check om den er sød
      } else {
          // uinteressant
      }
      return;
  }
  public boolean isPredator() {
      return true;
  }
}

public class Herring extends Fish {
  public void meetOtherFish(Fish f) {
      if(f.isPredator()) {
            // flygt
      } else {
            // ignorer
      }
      return;
  }
  public boolean isPredator() {
      return false;
  }
}
Avatar billede appel Novice
17. februar 2003 - 20:19 #26
Ja jeg kan se ideen, tror jeg vil viderudvikle på den...

Hvornår skal man lave abstrakte klasser og ikke bare lave en konkret og extende den ?

Du får pointene, for dine rigtig god hjælp!
Avatar billede arne_v Ekspert
17. februar 2003 - 20:26 #27
En normal klasse består kun af implementerede metoder.

Et interface består kun af abstrakte metoder.

En abstrakt klasse kan indeholde både implementerede metoder
og abstrakte metoder.

D.v.s. sådan en blanding.

An abstrakt klasse kan ikke instatieres. Og det passer jo meget godt
i dette tilfælde. Der er ikke nogen "Fish" objekter, men kun "Shark"
og "Herring" objekter. Fish er en abstraktion.

I dette tilfælde er de abstrakte metoder isPredator og meetOtherFish
nødt til at være abstrakte, da vi når de skal kaldes kun ved at vi
har en Fish men ikke hvilken.

Men vi ved at alle Fish har de metoder som modelerrer den pågældende
arts adfærd.

Og derfor kan vi bruge dem.
Avatar billede arne_v Ekspert
17. februar 2003 - 20:27 #28
Den abstrakte isPredator kaldes inde i meetOtherFish.

meetOtherFish kan så kaldes med (Fish)v.get(i) etc.
Avatar billede appel Novice
17. februar 2003 - 20:33 #29
Forøvrigt har jeg måske fundet et pattern til problemet : http://www.javaworld.com/javaworld/javatips/jw-javatip98.html?
Avatar billede arne_v Ekspert
17. februar 2003 - 20:44 #30
Visitor pattern er et meget kendt pattern.

Men jeg synes ikke det passer ikke helt til din problem-stilling.

Tricket med Reflection kunne du derimod godt have brugt til at finde
en metode med et argument af en type bestemt på runtime udfra
et objekt du har hentet ud af din Vector.

Men reflection er lidt tungt og jeg vil kun anbefale det i situationer,
hvor det er strengt nødvendigt.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester