Wie kann ich eine non-static Funktion aus anderer Klasse aufrufen?

  • Hallo zusammen,


    ich habe eine App, die mehrere Klassen umfasst. (funktionieren alle)


    Nun habe ich allerdings den Wunsch die Tipparbeit zu verringern.
    Momentan sieht es in einigen Klassen wie folgt aus:





    Schön wäre es, wenn ich diese non-static Funktion

    Java
    vibrate(...)

    nicht jedesmal schreiben muss, sondern diese in er einer tools Klasse auslagern könnte und von dort immer aufrufen könnte. Für statische Funktionen ist das ja recht einfach:


    Java
    public class Tools...{
       public static int rechne(int a, int b){
    		int c=a+b;		return c;	
       }
    }



    Was ja NICHT geht ist:


    Java
    import de.beispiel.app.Tools;
       public class MainActivity...{
       ...
       Tools.vibrate(500);
       ...
    }



    Das es nicht geht versteh ich weil das Objekt fehlt mit dem es interagieren soll.


    Preisfrage: Wie kann ich diese (oder andere) non-static Funktionen korrekt aufrufen?


    Vielen Dank im vorraus.

  • Das folgende Wissen stammt aus der Objective-C Welt und muss so nicht zu 100% auf Java portierbar sein. Ich finde es aber logisch und es funktioniert ähnlich, deshalb tue ich es dennoch.


    Zum Einen gibt es zwei Arten von Objekten in Java: Klassenobjekte und Instanzobjekte.
    Was immer man als Klasse erstellt ist an und für sich schon ein Objekt, denn es reagiert auf Nachrichten.


    new Class() ruft den Konstruktor des Klassenobjekts auf und legt ein Instanzobjekt nach den Vorgaben des gewählten Konstruktors an.
    Weiterhin verstehe ich 'static' als Klassenmethoden und non-static als Instanzmethoden.


    Das heißt, die als static gekennzeichneten Methoden benötigen zum Aufruf ausschließlich das Klassenobjekt.
    Deshalb gehen Dinge wie Collections.reverse(List<T>);


    Alle anderem Methoden benötigen zum Aufruf ein Instanzobjekt.
    Deshalb geht nicht Array.add(object);, sondern nur (new Array()).add(object);


    Demnach hast du zwei simple Möglichkeiten.
    Wann immer du dein Tools-Objekt benötigst, baust du dir ein Instanzobjekt davon.
    Also quasi (new Tools()).vibrate(500);


    Sinnvoll kann es aber auch sein, vibrate als Klassenmethode zu implementieren.
    Salopp:

    Java
    public class Tools...{
       public static void vibrate(int laenge) {
        /* Well, it's Java. 
        Das Device muss keinen Vibrator-Service haben, irgendwas könnte schief gehen etc.pp. 
        Errorhandling und Exceptionhandling sind also im Produktivcode angebracht. ;) */
        ((Vibrator)getSystemService(Context.VIBRATOR_SERVICE)).vibrate(laenge);
       }
    }


    Es kann natürlich durchaus passieren, dass du aus einer Static-Methode auf eine Non-Static Methode zugreifen möchtest, was dann zu Problemen führen kann.
    Aber ich denke, der generelle Ablauf dürfte erkennbar sein. :)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Du musst schon einen Konstruktor ausführen.
    Dieser sollte den Context der momentanen Activity beinhalten und dann kannst du deine Methode mit diesem Context aufrufen.
    So sollte es gehen ;)

    MfG,
    Christopher


    Eine gewisses Maß an Freundlichkeit kann man auch von Menschen im Internet erwarten.
    Das Forum basiert komplett auf der Freiwilligkeit ihrer Nutzer und diese sollen sich wohlfühlen! Daher seid bitte freundlich. Danke

  • Was spricht denn dagegen, die Methode einfach static zu machen?
    So wie Lucas de Vil schon angedeutet hat (nur das der Context noch mitgegeben wird)

    Code
    public static void vibrate(Context context, int length)
    {
        ((Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(length);
    }


    Diese Methode soll ja nicht den Zustand eines Objektes verändert, daher ist es in deiner Utility-Klasse ganz gut aufgehoben.


    block_

  • Vielen Dank für eure Antworten!


    das Problem konnte ich aber noch nicht lösen:


    Hier hab ich das gleiche Problem wieder:

    Zitat


    Cannot make a static reference to the non-static method getSystemService(String) from the type Activity


    Java
    public static void vibrate(int laenge) {
    		((Vibrator)getSystemService(Context.VIBRATOR_SERVICE)).vibrate(laenge);
    	}


    Und falls das obige gelöst wird...
    Wie soll dann der Aufruf aussehen? Was soll ich als context übergeben? Die aufrufende Klasse? Kann ich mir gerade nicht vorstellen.


    Java
    Tools.vibrate(MainActivity,500); //Denke das wird nicht funktionieren



    Java
    public static void vibrate(Context context, int length)
    {
        ((Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(length);
    }


    P.S. Gibt es nicht einfach soetwas wie in PHP "include"? Das würde mir die Sache schwer vereinfachen ;)

  • Hallo maalbert,


    es hat schon seine Richtigkeit dass du .getSystemService nicht ohne Context aufrufen kannst:
    Die meisten Systemservices brauchen ja bestimmte Rechte (welche du in er manifest Datei angeben musst). Also muss die getSystemService Funktion den "Context" kennen, um bestimmen zu dürfen ob du überhaupt diese Funktion ausführen darfst.


    Hier mein Lösungsansatz, wird wohl der "sauberste" sein. Allerdings würde ich vielleicht dann zwei Tools klassen machen, eine die initalisiert werden muss mit Context, und eine "normale".


    In deiner MainActivity:

    Java
    @Overrideprotected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Tools.initTools(this); 
    NotAnActivity test = new NotAnActivity(); 
    test.testVibrator(); 
    }


    Die Testklasse ohne verfügbaren "Context":

    Java
    public class NotAnActivity { 
    
    
    public void testVibrator(){ 
    Tools.vibrate(1000); 
    } 
    
    
    }



    PS: sorry keine Ahnung wieso mein source code so komisch formatiert ist, irgendwie funktionert das mit copy-paste und "java" flag hier im editor nicht so richtig.


    Gruss


    antifish

  • antifish
    Zwei Klassen für eine Hilfsmethode halte ich persönlich etwas zu viel.
    Statt der zweiten non-static Klasse kann man doch genauso gut direkt die statische Methode aufrufen. (Warum ist die Tools-Klasse abstract?)


    maalbert


    Und Aufruf in der Activity:

    Code
    Tools.vibrate(this, 1000);


    So mach ich das immer und es funktioniert einwandfrei.


    block_

  • antifish
    Zwei Klassen für eine Hilfsmethode halte ich persönlich etwas zu viel.
    Statt der zweiten non-static Klasse kann man doch genauso gut direkt die statische Methode aufrufen. (Warum ist die Tools-Klasse abstract?)


    Wenn du richtig schaust ist es nur eine Klasse, die andere ist nur zu Demonstration.
    Warum ist sie abstract? Verhindert instanzieren. Klar, Constructor private machen geht auch :)


    Deine Methode brauch genau mein .init weniger, allerdings musst du dann trotzdem IMMER den Context mitgeben, also bringt es dir gar nix wenn du in einer Klasse bist in der du keinen Zugriff auf den Context hast, ausser du löst das halt anderst, es gibt ja verschiedene möglichkeiten. Auch ein public static Context in der MainActivity währe möglich und immer das verwenden...

  • Zitat

    Okay, jetzt hab ichs verstanden :)
    Allerdings würde ich den Context auch nicht statisch halten. Was passiert dann wenn die Activity mit dem Context vom System destroyed wird? Dann gibts doch auch Probleme und um das zu umgehen musst trotzdem in jeder Activity deine init() Methode ausführen.


    block_


    Ja das stimmt, kann zb bei mehreren activities ein Problem sein, da währe deine Lösung sicherer. Ist immer schwierig ohne die ganze App zu kennen.


    Lg antifish

  • Ginge statt Übergabe von Context auch einfach ein getBaseContext() in der Static Methode?

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Geil! Geht!


    Vielen Dank!


    So läuft es bei mir gerade wunderbar, melde mich wieder in einem neuen Thread wenn es wieder irgendwo hängt.


    Java
    public class Tools...{
       public Vibrator vibrator;
       public static void vibrate(Context context,int laenge) {
    		((Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(laenge);
       }
    }


    Java
    public class MainActivity...{
       public void testVibrator(){ 
          Tools.vibrate(this, 1000); 
       } 
    }

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!