Avatar billede Slettet bruger
25. februar 2004 - 12:02 Der er 17 kommentarer og
3 løsninger

Lave metodekald udfra en tekststreng indeholdende metodens navn

Hejsa eksperter, jeg ville blot høre om det var muligt at lave et metodekald udfra en String indeholdende navnet på en metode i en klasse....

Lad os sige jeg har følgende klasse:

class Person {
  private String navn = "hej";

  public String getNavn() { return navn; }
}

Hvordan får jeg så kaldt metoden getNavn (forudsat jeg har en instans af objektet, naturligvis)... Har det ikke noget med reflection at gøre....

Det jeg søger efter er et "hands on" / konkret eksempel, samt nogle links om dette emne? Jeg ved bare ikke helt om jeg skal begi' mig i krig med dette emne, eller implementere mit ønskede system vha. en anden fremgangsmåde....

60 point (jow, det er dælme svært for mig) til den som giver et eksempel, samt nogle links...

På forhånd tak, Anders :-)
Avatar billede jakoba Nybegynder
25. februar 2004 - 13:19 #1
Jeg er ikke sikker på jeg forstår. Hvorfor ikke blot:

Person corholio = new Person();
              // lav en instans af den klasse

System.out.println( corholio.getNavn() );
              // og brug så instansen til at udpege hvor metoden getNavn skal udføres

uden ændringer i din klasse 'Person'
Avatar billede jakoba Nybegynder
25. februar 2004 - 13:27 #2
Her er et eksempel der viser hvorfor det kan være vigigt at vide hvilken instans af klassen metoden bliver kaldt i:

class Person {
  private String navn;
  public Person( String navn ) { this.navn = navn ) //end constructor
  public String getNavn() { return navn; } //end method
} //endclass Person

public class TestProg {
  public void main( String[] args ) {
    Person corholio = new Person( "Anders" );  // lav en instans af den klasse
    Person jakoba = new Person( "Jakob" );      // lav en instans af den klasse
              // de forskellige instanser af Person har forskellige værdier
              // i deres navn variabel

    System.out.println( corholio.getNavn() );
    System.out.println( jakoba.getNavn() );
              // brug instansen til at udpege hvor metoden getNavn skal udføres
  } //end method main
} //endclass TestProg

mvh JakobA
Avatar billede Slettet bruger
25. februar 2004 - 13:29 #3
det er fordi jeg vil ha' metodekaldet til at ske ud fra en parameter, altså noget i stil med:

public void kaldMetode(Object mitObjektAtKalde, String metodeNavn) {
    //kald metoden med navn "metodeNavn" i objektet mitObjektAtKalde...
}

Det er forskelligt fra gang til gang hvilken metode som skal kaldes på objektet, og disse (mange) forskellige metodekald skal kunne kaldes fra een metode af
Avatar billede bearhugx Nybegynder
25. februar 2004 - 13:37 #4
corholio >> men hvad har du så tænkt dig at stille op mht. argumenter til metoden ???

Hvis det er du vil lave en kaldMetode(etObj, enMetode), så burde den jo næsten udvides til
  kaldMetode( obj, metode, args );

og hvis du vil igang med dette, ja, så skal du igang med reflection...

Det er et stykke tid siden, jeg har arbejdet med det - men kan måske lave et lille eksempel...

BEMÆRK dog at reflection ikke er nogen god ide hvis det kan laves anderledes, ved at ændre arkitekturen lidt -- at skulle til at slå metoder op etc og al den exceptionhandling, som skal omkredse det gør at reflection kun er det værd i få tilfælde...
Avatar billede Slettet bruger
25. februar 2004 - 13:47 #5
Det kan da godt være at jeg skulle revurdere min arkitektur - nåååh....hvis du smider et eksempel på brug af reflection, bearhugx, får du pointene - jeg skal under alle omstændigheder lige prøve det af....
Avatar billede jakoba Nybegynder
25. februar 2004 - 13:48 #6
Det ville jeg gøre med en switch og en (lang) streng der indeholder alle gyldige navne:

Final String langKonstantStreng = " " +  // forste led er et enkelt blanktegn
    "getNavn        " +            // hvert 'led' i strengen er 16 bogstaver langt
    "getAdresse    " +
    "getSkoNummer  " +
//  ... osv osv
    "getNogetAndet  ";

public Sting gørNogetDerReturnererEnStreng( String metodeNavn ) {
    int metodeIndex = langKonstantStreng.indexOf( " " + metodenavn + " " );
    if ( metodeIndex >= 0 ) metodeIndex /= 16;
    switch ( metodeIndex ) {
        case 0: return getNavn();  // vi returnerer så der er ikke brug for break;
        case 1: return getAdresse();
        case 2: return getSkoNummer();
//      ... osv, osv
        case N: return getNogetAndet();
        default return "Det er noget galt her";
    }
} //endmethod gørNogetDerReturnererEnStreng

mvh JakobA
Avatar billede Slettet bruger
25. februar 2004 - 13:50 #7
det begyndte jeg også lige selv at tænke på.... *sigh* søvnmangel er sq' en forfærdelig ting :-| ....

Jeg venter lige og ser om bearhugx smider et eksempel, så får i lige en 30/70 fordeling af pointene
Avatar billede jakoba Nybegynder
25. februar 2004 - 13:59 #8
fint no :)  Og undskyld the totale 'newbiesvar' først. Det det kan være grumme svært at gætte hvor en spørger står og her skød jeg lovlig langt forbi.

mvh JakobA
Avatar billede bearhugx Nybegynder
25. februar 2004 - 14:04 #9
lig mig lige en 10-15 minutter til at lave et eksempel...
Avatar billede arne_v Ekspert
25. februar 2004 - 14:22 #10
Simpelt reflection eksempel:

import java.lang.reflect.*;

public class R {
    public static void m1(String a, String b) {
        System.out.println("m1: " + a + " " + b);
    }
    public static void m2(String a, String b) {
        System.out.println("m2: " + a + " " + b);
    }
    public static void c(String className, String methodName, String a, String b) {
        try {
            Class declarg[] = new Class[2];
            declarg[0] = String.class;
            declarg[1] = String.class;
            Method m = Class.forName(className).getMethod(methodName, declarg);
            Object callarg[] = new Object[2];
            callarg[0] = a;
            callarg[1] = b;
            m.invoke(null, callarg);
        } catch (Exception e) {
        }
    }
    public static void main(String[] args) {
        m1("a", "b");
        m2("a", "b");
        c("R", "m1","a", "b");
        c("R", "m2","a", "b");
    }
}
Avatar billede Slettet bruger
25. februar 2004 - 14:23 #11
Tusind tak, arne_v... men vil du ikke være venlig at ligge et svar så du kan få nogle point?
Avatar billede bearhugx Nybegynder
25. februar 2004 - 14:26 #12
dette er ikke aftestet (jeg har ikke java på denne computer, så det er skrevet fra hukommelsen) ...

import java.lang.reflect.*;

class ReflectionTest
{
    public String denneMetodeVilJegKaldeFordiDensNavnErIEnTekstStreng( String msg ) {
        System.out.println(" Hejsa fra den lange metode - her er beskeden : "+msg);
        return "ok";
    }

    public ReflectionTest() {
        String metodeNavn = "denneMetodeVilJegKaldeFordiDensNavnErIEnTekstStreng";
        String msg = "hej corholio og jacoba";

        ReflectionTest obj = this;
        Class enRTClass = this.getClass();
        Class[] argumentTypeListe = new Class[] {String.class}; // En array med en String - da vi ønsker at ramme den variant, som kun tager en String som argument
        Object[] argumenter = new Object[] {msg};

        Method metoden;
        String resultat;
        try    {
            metoden = enRTClass.getMethod( metodeNavn, argumentTypeListe ); // Her hentes en ref. til metoden med de rette argument-typer
            resultat = (String) metoden.invoke( obj, argumenter );
        } catch (NoSuchMethodException e) {
            System.out.println(e);
        } catch (IllegalAccessException e) {
            System.out.println(e);
        } catch (InvocationTargetException e) {
            System.out.println(e);
        }
        return resultat;
    }



    public static void main(String[] args) {
        new ReflectionTest();
    }
}
Avatar billede Slettet bruger
25. februar 2004 - 14:26 #13
og du må også godt smide et svar, bearhugx.... ;-)
Avatar billede bearhugx Nybegynder
25. februar 2004 - 14:27 #14
arne >> he he :-) kan se at du har været inde og sprede guldkorn :-=)
Avatar billede bearhugx Nybegynder
25. februar 2004 - 14:27 #15
^svar^
Avatar billede arne_v Ekspert
25. februar 2004 - 14:28 #16
svar
Avatar billede Slettet bruger
25. februar 2004 - 14:31 #17
Pointfordelingen blev så 6, 27, 27.... fordi JakobA fik min hjerne til at revurdere min arkitektur, og så arne_v og bearhugx dele resten, da de begge kom med eksempler med brug på reflection....

Tusing tak for hjælpen :-)
Avatar billede arne_v Ekspert
25. februar 2004 - 14:31 #18
Eksemplet jeg havde liggende og kunen bygge på var med static metode i ukendt
klasse.

bearhugx er med ikke static metode og kendt klasse.

Der er en del variationer.
Avatar billede arne_v Ekspert
25. februar 2004 - 14:33 #19
Min i bearhugx kompatibel udgave:

import java.lang.reflect.*;

public class R2 {
    public void m1(String a, String b) {
        System.out.println("m1: " + a + " " + b);
    }
    public void m2(String a, String b) {
        System.out.println("m2: " + a + " " + b);
    }
    public static void c(Object o, String methodName, String a, String b) {
        try {
            Class declarg[] = new Class[2];
            declarg[0] = String.class;
            declarg[1] = String.class;
            Method m = o.getClass().getMethod(methodName, declarg);
            Object callarg[] = new Object[2];
            callarg[0] = a;
            callarg[1] = b;
            m.invoke(o, callarg);
        } catch (Exception e) {
        }
    }
    public static void main(String[] args) {
        R2 r = new R2();
        r.m1("a", "b");
        r.m2("a", "b");
        c(r, "m1","a", "b");
        c(r, "m2","a", "b");
    }
}
Avatar billede bearhugx Nybegynder
25. februar 2004 - 14:37 #20
takker for points :-)
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