Gå til innhold

Kall utenfra / Events


Anbefalte innlegg

Prøver å lære meg litt basic java.

Utfordringen er å la B-objektet kalle på en metode i A-objektet. Men B skal ikke behøve å vite på forhånd hva slags klasse A-objektet er bygget på. Dette kalles events i Delphi Pascal, men jeg tror ikke det er det samme som events i Java...

Er det noen som kan foreslå en oversettelse fra Pascal til Java av denne koden?

 

Vi starter i TAAAAAAAA.RunThisFirst

Her lages B og forteller B at ProcToBeCalled er en procedure i A.

Så kalles B sin CallNow.

CallNow sjekker om ProcToBeCalled kan kalles (Assigned), og i så fall kalles denne. Det medfører at ProcCalledFromBBBBBBBB kjøres.

 

unit Unit1;

interface

type
 TBBBBBBBB = class(TObject)
 public
   ProcToBeCalled : procedure (Nr: Integer) of object;
   procedure CallNow;
 end;
 TAAAAAAAA = class(TObject)
 private
   BBBBBBBB : TBBBBBBBB;
   procedure ProcCalledFromBBBBBBBB(Nr : Integer);
 public
   procedure RunThisFirst;
 end;

implementation

procedure TAAAAAAAA.RunThisFirst;
begin
 try
   BBBBBBBB := TBBBBBBBB.Create;
   BBBBBBBB.ProcToBeCalled := Self.ProcCalledFromBBBBBBBB;
   BBBBBBBB.CallNow;
 finally
   BBBBBBBB.Free;
 end;
end;

procedure TBBBBBBBB.CallNow;
begin
 if Assigned(ProcToBeCalled) then ProcToBeCalled(5);
end;

procedure TAAAAAAAA.ProcCalledFromBBBBBBBB(Nr: Integer);
begin
 // BBBBBBBB called this procedure
end;

end.

Lenke til kommentar
Videoannonse
Annonse

Jeg skjønner ikke helt hva du mener med den "Men A objektet trenger ikke vite på forhånd hva slags klasse B er bygget på". Mener du da at A har fått B som en Object klasse? Eller har du laget ett B object med B b = new B();? Hvis det er det siste kan du jo bare bruke b.<metode>();

Hvis ikke er jeg ikke helt sikker. Kan vel forsøke en try/catch som dette:

 

try {
B trycatch = (B) b;
trycatch.<metode>();
} catch(Exception e) {
<Fin feilmelding>
}

 

Nå vet jeg ikke hvilken exception noe sånt vil gi, så du burde finne ut av det og bytte ut Exception med det det faktisk skal være. Exception e vil nok fungere, siden Exception er en superklasse av alle andre Exceptions, men er ikke spessielt informativt for en som eventuelt skal lese koden din i ettertid.

Lenke til kommentar

Det stemmer at jeg har laget et B-objekt i klassen A, ja.

BBBBBBBB := TBBBBBBBB.Create;  // Pascal
TBBBBBBBB BBBBBBBB = new BBBBBBBB();  // Java. Beklager tåpelige navn...

Poenget er ikke at A skal kalle på en metode i B, men at B skal kalle på en metode i A som den ved kompilering ikke vet adressen til. Den vet bare "event"-navnet. Dette tilsvarer en peker som peker på startadressen til en metode.

Jeg skrev :

Men B skal ikke behøve å vite på forhånd hva slags klasse A-objektet er bygget på.
. Jeg ønsker å lage klassen B slik at den kan kalle en procedure/method i A (ProcCalledFromBBBBBBBB). Men A er ikke medlem av B, så derfor kan jeg ikke skrive A.ProcCalledFromBBBBBBBB.

Hvorfor vil jeg dette? Jo, sett at jeg har en klasse C som også har en ProcCalledFromBBBBBBBB, så vil jeg at B skal kunne kalle C sin ProcCalledFromBBBBBBBB når et annet objekt B blir instantiert fra C. Dermed har både klassen A og klassen C hvert sitt eget objekt av klassen B. Når B-objektet i A-klassen vil kalle sin ProcToBeCalled er det AAAAAAAA.ProcCalledFromBBBBBBBB som blir kalt. Når B-objektet i C-klassen vil kalle sin ProcToBeCalled er det CCCCCCCC.ProcCalledFromBBBBBBBB som blir kalt.

Endret av lefodnes
Lenke til kommentar

Vel. Nå er jeg litt usikker på hva du mener med at B ikke er medlem av klassen A. Mener du da at B ikke har noen peker til A eller at B ikke arver noe fra A? Hvis B skal kalle en metode i A må B ha en peker til A. Siden A lager B objektet kan du jo bare sende med objektet A da du lager B. Altså at konstruktøren til B ser noe sånn her ut.

 

A a;

B(<det du allerede har>, A a) {
<De kallene du allerede har>;
  this.a = a;
}

 

Hvis det ikke er noe spessiell data som er spesifikt for det objektet i A, men som alle A objekter har kan du kalle på metoden ved

 

new A(<paramtere for konstruktøren til A>).metode();

 

En peker kreves hvertfall fra B til A for at B skal kunne kalle noen metoder i A. Kunne kanskje hjulpet å forstå litt hvis du pasta noe av java koden din?

Endret av NevroMance
Lenke til kommentar

Tusen takk for at du prøver å hjelpe meg!

Jeg byttet om på A og B et lite øyeblikk der, har rettet det opp.

"B ikke er medlem av A" skulle vært "A ikke er medlem av B", og jeg mener at det finnes ikke noe objekt/varabel A i klassen B. A og B arver ikke hverandre. De er to klasser som arver en felles klasse.

Hvis B skal kalle en metode i A må B ha en peker til A.

Nesten sant! (i hvertfall når det gjelder pascal) I pascal holder det at B har en peker til metoden i A. Denne pekeren heter i mitt pascal-eksempel ProcToBeCalled. Pekeren blir i "RunThisFirst" satt til å peke på metoden "ProcCalledFromBBBBBBBB". Kanskje kan spørsmålet mitt formuleres til å være : Er en metode/procedure/funksjon basert på arvbar "klasse", slik at pekeren til bare metoden kan sendes inn til et objekt?

Siden A lager B objektet kan du jo bare sende med objektet A da du lager B. Altså at konstruktøren til B ser noe sånn her ut.

 

A a;

B(<det du allerede har>, A a) {
<De kallene du allerede har>;
  this.a = a;
}

OK, men hvis jeg nå vil ha en klasse A og C slik:

public class C {
 private B b;
 public C() {
B b = new B(C)
 }
}

public class A {
 private B b;
 public A() {
B b = new B(A) 
 }
}

 

Kompilatoren vil nekte på linje 4! Den vil si at du kan ikke sende inn C som parameter i B sin constructor, for denne parameteren skal være av klasse A. (iflg din constructor)

Lenke til kommentar

I du initialiserer også to forskjellige B'er, da du kalle new B to ganger. Vet ikke om det er noen måte å kalle en metode i Java uten en peker til objektet med metoden. Sånn som jeg ser det du har laget der ville jeg nok også ha laget en peker fra A til C, Forutsatt at B objektene i C og A skal være den samme? Det som går for å ikke lage tull i contructøren er jo å ta imot ett Object. Da Object er superklassen til alle objekter kan Object brukes uansett om det er A eller C du bruker.

 

Hvis du da igjen skal ha x-antall pekere til den samme Ben tror jeg faktisk du må lage en liste, altså pekere mellom disse objektene som skal ha en peker til B, for at de skal få den samme Ben. Hvis det ikke trenger være den samme er det ikke så farlig. Skal du samtidig ha tilgang til en metode i alle de som peker til B må du ha en tilbakepeker fra B til alle de andre. Så sånn som jeg har forstått deg hittil vil dette bli ett veldig stort pekerkaos.

 

Er ingen muligheter for å endre litt tankemåte? F. eks. la B styre hele programmet. I mitt hode blir det litt ulogisk at A skal styre B, mens B skal sette i gang noen metodekall i A, samtidig som C skal styre B og B skal starte metoder i C. Jeg ville prøvd å la B styre, hvis dette er mulig for oppgaven(?), eller lage en klasse som styrer A og C. og starter en metode i A avhengig av en returverdi fra C eller noe? Sånn som jeg har forstått det vil det hvertfall bli fryktelig mye pekere rundt om kring, hvertfall hvis du har flere klasser enn de 2 som skal tulle rundt med B.

Lenke til kommentar
Prøver å lære meg litt basic java.
Og lykke til!
Utfordringen er å la B-objektet kalle på en metode i A-objektet.
a.method();
Men B skal ikke behøve å vite på forhånd hva slags klasse A-objektet er bygget på.
Da har B kun tilgang til de metodene som A arver fra Object. Du vil muligens at A skal implementere et interface? Da kan B kjøre alle metodene som er i både Object og i det implementerte interfacet.
Dette kalles events i Delphi Pascal, men jeg tror ikke det er det samme som events i Java...
Mye mulig ikke.
Er det noen som kan foreslå en oversettelse fra Pascal til Java av denne koden?

Vi starter i TAAAAAAAA.RunThisFirst
Her lages B og forteller B at ProcToBeCalled er en procedure i A.
Så kalles B sin CallNow.
CallNow sjekker om ProcToBeCalled kan kalles (Assigned), og i så fall kalles denne. Det medfører at ProcCalledFromBBBBBBBB kjøres.

Hmm ... Interessant nok, men å programmere krever at man også tenker på den måten programmeringsspråket fungerer.

 

Selv om jeg gjerne vil skrive samtlig kode i Prolog og Lisp rekursivt, betyr det ikke at jeg ville gjort det i Java.

 

Kan du komme med et bedre (i.e. mer håndfast) eksempel på hva du egentlig vil?

 

Poenget er ikke at A skal kalle på en metode i B, men at B skal kalle på en metode i A som den ved kompilering ikke vet adressen til. Den vet bare "event"-navnet. Dette tilsvarer en peker som peker på startadressen til en metode.
Ett eller annet sted må referansen til A ligge. Og hvis ikke B har en peker til den, må B ha en peker til noe annet som har en peker til A, eller noe som har en peker til noe som har en peker til A.

 

Kompilatoren vil nekte på linje 4! Den vil si at du kan ikke sende inn C som parameter i B sin constructor, for denne parameteren skal være av klasse A. (iflg din constructor)
Hva er det egentlig du vil?
Lenke til kommentar

Takk for nyttig innspill!

Jeg må selvsagt være åpen for andre måter å tenke på. Jeg synes likevel events i Delphi Pascal er veldig nyttig. Det gjør at jeg kan bruke source-fila til B-klassen i mange forskjellige prosjekter om og om igjen. B-klassen vil ha metoder, hvor jeg bruker noen i enkelte tilfeller og andre i andre tilfeller.

Jeg har også tenkt på det å sende inn et Object eller en superklasse med en abstract metode, men da må alle klassene som lager B-objekter være arvet av denne superklassen. Mulig det går hvis det går an hvis man kan arve flere klasser samtidig. Hvis Object brukes, må jeg typecaste til en kjent klasse, og det er det som er om å gjøre å unngå. Dvs. B skal ikke vite hvem den blir brukt av. På denne måten blir B universell og ikke avhengig av hverken A eller C.

Nytt eksempel:

public class B {
 public int msInterval;
 public int id;
 public event onTimer;
 public B(int id, int msInterval) {
this.msInterval = msInterval;
this.id = id;
 }
 <... mer kode for å lage en timer / thread eller hva som må til ...>
}

public class A {
 private B alfa;
 private B beta;
 private B gamma;
 private void alfaTimer() { Alert a = new Alert("alfa", "Alfa timer", null, AlertType.ERROR); }
 private void betaTimer() { Alert a = new Alert("beta", "Beta timer", null, AlertType.ERROR); }
 private void gammaTimer() { Alert a = new Alert("gamma", "Gamma timer", null, AlertType.ERROR); }
 public A() {
B alfa = new B(2, 200);
alfa.onTimer = alfaTimer;
B beta = new B(3, 150);
beta.onTimer = betaTimer;
B gamma = new B(5, 300);
gamma.onTimer = gammaTimer;
 }
}

Dette vil jo ikke virke. Her har jeg prøvd å blande litt pascal og java, for å illustrere litt bedre. Objektene alfa, beta og gamma er her verktøy for klassen A. Ingen av objektene kan dermed være ansvarlig for å "styre programmet". A gir beskjed til alle 3 objektene om at de skal gi beskjed hver gang de får en trigg, men de får ikke vite hva som skal skje.

 

Når jeg finner ut at jeg skal lage et nytt prosjekt C, linker jeg inn sourcekoden for klasse B slik at om jeg forbedrer B når jeg jobber videre med prosjekt C, så vil forbedringene komme prosjekt A til gode.

Lenke til kommentar
Du vil muligens at A skal implementere et interface? Da kan B kjøre alle metodene som er i både Object og i det implementerte interfacet.
Takk! Det er mulig "interface" er stikkordet jeg leter etter.
Poenget er ikke at A skal kalle på en metode i B, men at B skal kalle på en metode i A som den ved kompilering ikke vet adressen til. Den vet bare "event"-navnet. Dette tilsvarer en peker som peker på startadressen til en metode.
Ett eller annet sted må referansen til A ligge. Og hvis ikke B har en peker til den, må B ha en peker til noe annet som har en peker til A, eller noe som har en peker til noe som har en peker til A.
Virkelig?? Vel, ok, hvis det er slik for Java, så.. Men søren og... Kunne du ikke ha skrevet "Ett eller annet sted må referansen til metoden ligge? Jeg kjenner ikke til dypet av Java, men en metode ligger vel lagret i Java-maskin-kode på en eller annen adresse, som en peker kan peke på? Og B, når den har denne pekeren, kan kalle denne metoden vha. pekeren, ikke vha. objektet metoden ligger i. Selvsagt er det en utfordring for kompilatoren som må forstå at koden kjøres med objektdata fra det objektet som har satt referansen...

 

Hva er det egentlig du vil?
Jeg prøver å gjøre B uavhengig av A og C. Jeg har en følelse av at dette ender opp som en diskusjon om hva som er beste språk...
Lenke til kommentar
Hva er det egentlig du vil?
Jeg prøver å gjøre B uavhengig av A og C. Jeg har en følelse av at dette ender opp som en diskusjon om hva som er beste språk...
Det trenger det nok ikke å ende opp i.

 

Du må uansett vite metodenavnet (ikke søk etter java reflection ennå). La meg ta et eksempel, så kan du si om det er noe helt annet du er ute etter:

 

Dersom du ønsker å lage en generell sorteringsmetode (f. eks. implementere din egen merge- eller quicksort), må du vite hvordan man kan sammenligne objektene du skal sortere. Du må på ett eller annet vis bruke en metode som du vet kan gi noe vetig mtp. naturlig orden.

Der kommer interfacet Comparable<T> inn i bildet. Dersom du lager en metode for å sortere, kan du ta inn en hvilken som helst samling av objekter som alle implementerer Comparable, for da vet du det eksisterer en metode compareTo(Comparable<T> t) som returnerer en tallverdi.

Lenke til kommentar

La oss si at du har et objekt A (et panel) som inneholder et objekt B (f.eks en knapp), du kan da legge til en action-listener til knappen B som kaller en metode på objekt A når noen trykker på knappen B.

 

Da vil ikke objekt B vite om objekt A, men får allikevel kalt opp metoder på objektet. Det er slik gui-en fungerer i java.

 

http://java.sun.com/docs/books/tutorial/uiswing/

når du har forstått basis-konseptet kan du gå til

http://java.sun.com/docs/books/tutorial/ui...ents/index.html

 

La oss si at du har et objekt A (et panel) som inneholder et objekt B (f.eks en knapp), du kan da legge til en action-listener til knappen B som kaller en metode på objekt A når noen trykker på knappen B.

 

Da vil ikke objekt B vite om objekt A, men får allikevel kalt opp metoder på objektet. Det er slik gui-en fungerer i java.

 

http://java.sun.com/docs/books/tutorial/uiswing/

når du har forstått basis-konseptet kan du gå til

http://java.sun.com/docs/books/tutorial/ui...ents/index.html

Lenke til kommentar

Har prøvd å få med meg hva trådstarter egentlig ønsker å få til her (uten å helt ha lykkes). Her er min tolkning:

 

Klasse B skal ha en masse metoder som skal kunne ta inn objekter (feks klasse A) som den skal gjøre noe med (kalle noen metoder). Dette skal skje uten at B nødvendigvis trenger å vite hvilke klasse objektet (A) er en instanse av.

 

Da er det et par små ting som må avklares:

 

1. Vet man hva disse metodene heter og hvilke paremetertyper de har ved kompilering, eller er denne informasjonen bare tilgjengelig ved runtime? (uansett hvordan man vrir og vender på må ma alltid ha en referanse/peker til metoden som skal kalles og dersom metoden ikke er definert som static må man også ha referansen til objektet som den skal kjøres i)

 

2. Hva er det egentlig klasse A og B skal gjøre? Er en fordel å ha litt mer info for å kunne gi litt mer konkrete tips.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...