2012-09-27 26 views
17

Powiel możliwe:
Java Pass Method as ParameterJak przekazać metodę jako parametr w Javie?

Czy to możliwe, aby przekazać metodę jako parametr w Java? Jeśli nie mogę zrobić najlepszego sposobu działania dla poniższej metody bez konieczności powtarzania kodu.

public void enterUserInput(javax.swing.JTextField inputField, javax.swing.JTextField outputField, method rangeChecking){ 

    String input; 
    double output; 
    input = inputField.getText(); 
    output = Double.parseDouble(input); 
    if(rangeChecking(output)){ 
     outputField.setText(input); 
     inputField.setText(null); 
    } 

będę wywołanie metody rangeChecking z innej klasy i za każdym razem nazywamy enterUserInput metoda rangeChecking będzie inna

+12

[Interfejs - metoda Java Pass jako parametr] (http://stackoverflow.com/questions/2186931/java-pass-method-as-parameter?rq=1) – Aerus

+0

Zobacz także tę odpowiedź http: // stackoverflow. com/a/22933032/1010868 –

Odpowiedz

6

Nie o ile wiem. Na ogół jest to zrobić poprzez interfejs, który posiada metodę, którą chcesz i przechodzącej klasy, która implementuje ten interfejs w.

public interface IRangeCheck 
{ 
    boolean check(double val); 
} 

public class RangeChecker implements IRangeCheck 
{ 
    public boolean check(double val) 
    { 
     return val > 0.0; 
    } 
} 

... 
    public void blabla(..., IRangeCheck irc) 
    { 
     ... 
     if(irc.check(output)) 
      ... 
    } 
+1

@CrazyCasta .. To nie jest Java. Powinieneś napisać 'implementuje IRangeCheck' aby zaimplementować interfejs .. –

+2

niezależnie, koncepcja stoi .. – jrharshath

+0

@RohitJain Dobry połów, minęło trochę czasu Właściwie napisałem coś w Javie. – CrazyCasta

32

należy użyć interface to zrobić.

Zdasz interfejs, który deklaruje żądaną funkcję do metody i wywołać odpowiednią metodę. Konkretną metodą, która zostanie wywołana, jest metoda zaimplementowana przez klasę implementującą.

To się nazywa strategy design pattern.

przykładowy kod:

public static interface Foo { //this is the interface declaration 
    public void print(); 
} 
public static class Bar implements Foo { //Bar is an implementing class 
    public void print() { 
     System.out.println("Bar"); 
    } 

} 
public static void test(Foo foo) { //the method accepts an interface 
    foo.print(); //and invokes it, the implementing class' print() will be invoked. 
} 
public static void main(String... args) throws Exception { 
    test(new Bar()); //invoke test() with the class implementing the interface 
} 
+2

Dzięki ... nauczyłem się czegoś nowego dzisiaj :) :) – Amarnath

+1

Gdybym miał wybrać wzór przypominający ten pomysł, wybrałbym wzór polecenia. Stategy brzmią zbyt skomplikowanie, zazwyczaj oznacza to kilka implementacji. –

+0

@amit dlaczego zadeklarowałeś, że interfejs jest statyczny? – Celeritas

6

Załóż interfejs z tym podpisem metody i przekazać anonimowe podklasy go z implementacji metody.

// the interface that contains the method/methods you want to pass 
interface MethodWrapper { 
    public void method(String s); } 

// ... 
// in your code 
// assuming that "observable" is an object with a method "setCallback" that 
// accepts the callback 
// note that your method implementation will have access to your local variables 

public void someMethodOfYours() { 
    observable.setCallback(new MethodWrapper() { 
     public void method(String s) { 
      System.out.println(s); 
     } } 
    ); 
    // note that your anon subclass will have access to all your contain method 
    // locals and your containing class members, with [some restrictions][1] 
} 

// in the "observable" class - the class that receives the "callback method" 
// ... 

if(updated()) { 
    callback.method("updated!"); } 

W przyszłych wersjach Java (wraz z nadejściem lambda) nie będzie musiał zdefiniować interfejs i anonimowej klasy wewnętrznej - nie będzie specyficzna składnia lambda, która zostanie skompilowany do kodu bajtowego równoważnej.

[1] Cannot refer to a non-final variable inside an inner class defined in a different method

+0

Java 7 nie ma wyrażeń lambda. Może Java 8 będzie je mieć kiedyś w przyszłości. – Jesper

+0

należycie zanotowano - edytując odpowiedź odpowiednio. – jrharshath

2

można utworzyć interfejs, który określa potrzebną sposób i przekazać obiektu klasy, która realizuje ten interfejs. Często używa się do tego anonimowych klas.

interface Worker { 
    public void callMe(); 
} 

public function callWorker(Worker w) { 
    w.callMe(); 
} 

callWorker(new Worker() { 
    public void callMe() { 
     System.out.println("Hi there!"); 
    }); 
1

Nie można przekazać metody w języku Java.

czego nie deklaruje interfejs, a uzyskanie jako parametr klasy, która implementuje interfejs, w ten sposób możemy wywołać funkcję poprzez parametr.

możesz w swoim kodzie utworzyć anonimową klasę.

5

Możesz używać refleksji java.

public void enterUserInput(javax.swing.JTextField inputField, javax.swing.JTextField outputField, String methodName){ 

String input; 
double output; 
input = inputField.getText(); 
output = Double.parseDouble(input); 
Method m = this.getClass().getDeclaredMethod(methodName, Double.class); 

if((Boolean)m.invoke(this, output)){ 
    outputField.setText(input); 
    inputField.setText(null); 
} 
+2

Powinieneś obsłużyć przypadek, gdy wymagana metoda należy do klasy przodków i/lub kompatybilna metoda ma inny podpis. 'void foo (double d)' nie będzie pasowało do 'getDeclaredMethod' jeśli podasz' Double.class'. – Stephan

+1

Powinieneś naprawdę używać funkcji językowych, takich jak rozwiązanie z interfejsami prezentowanymi przez innych, zamiast refleksji. Odbicie nie jest bezpieczne i wolniejsze niż zwykłe wywołania metod. – Jesper

1

Nie, przekazanie metod jako argumentu nie jest możliwe.

Myślę, najlepszym rozwiązaniem jest stworzenie interfejsu, napisać klasy, która implementuje że (zmodyfikować realizację, jak trzeba) i przekazać obiekt klasy jako argument.

Możesz również użyć odbicia, przekazać metodę method jako ciąg do metody. i użyj odbicia, aby wywołać tę metodę.

Nadzieja to pomaga :-)

4

Istnieją sposoby, można to zrobić za pomocą Reflection ale to najlepiej unikać. Co chcesz zrobić, to utworzyć interfejs jak:

public interface RangeChecker { 

    boolean rangeChecking(double input); 


} 

następnie utworzyć wdrożeń dla każdej z metod sprawdzających zakres:

public class SomeRangeCheck implements RangeChecker { 

    public boolean rangeChecking(double input) { 
     // do something 
    } 

} 

Potem podpis Twojego inna metoda staje się:

public void enterUserInput(JTextField inputField, JTextField outputField, RangeChecker rangeChecking) 

Że możesz przekazać dowolny obiekt, który implementuje interfejs RangeChecker.

Powiązane problemy