Czy istnieje sposób przekazania funkcji wywołania zwrotnego w metodzie Java?
Zachowanie, które próbuję naśladować, to przekazywanie delegata .Net do funkcji.
Widziałem, jak ludzie sugerowali stworzenie oddzielnego obiektu, ale wydaje się to przesada, jednak jestem świadomy, że czasami przesada jest jedynym sposobem na zrobienie czegoś.
java
callback
function-pointers
Omar Kooheji
źródło
źródło
Odpowiedzi:
Jeśli masz na myśli coś w rodzaju anonimowego delegata .NET, myślę, że można również użyć anonimowej klasy Javy.
źródło
Od wersji Java 8 istnieją odwołania do lambda i metod:
Na przykład, jeśli potrzebujesz funkcjonalnego interfejsu,
A -> B
takiego jak:możesz to tak nazwać
Możesz również przekazać metodę klasową. Powiedz, że masz:
Następnie możesz:
Uwaga :
Tutaj użyłem funkcjonalnego interfejsu
Function<A,B>
, ale w pakiecie jest wiele innychjava.util.function
. Najbardziej godne uwagi sąSupplier
:void -> A
Consumer
:A -> void
BiConsumer
:(A,B) -> void
Function
:A -> B
BiFunction
:(A,B) -> C
i wiele innych, które specjalizują się w niektórych typach wejścia / wyjścia. Następnie, jeśli nie zapewnia tego, którego potrzebujesz, możesz stworzyć własny funkcjonalny interfejs, taki jak:
Przykład użycia:
źródło
java.util.function
szukasz czegoś, czego szukasz, to możesz iść. Następnie możesz bawić się typami dla I / O. (?)java.util.function
nie są wystarczające.Dla uproszczenia możesz użyć Runnable :
Stosowanie:
źródło
public interface SimpleCallback { void callback(Object... objects); }
Jest to dość proste i może być przydatne, ponieważ musisz również przekazać kilka parametrów.Trochę czepiania się:
Przekazywanie wywołania zwrotnego obejmuje utworzenie oddzielnego obiektu w prawie każdym języku obiektowym, więc nie można go uznać za przesadę. Prawdopodobnie masz na myśli to, że w Javie wymaga to utworzenia oddzielnej klasy, która jest bardziej szczegółowa (i wymaga więcej zasobów) niż w językach z jawnymi funkcjami lub zamknięciami pierwszej klasy. Jednak klasy anonimowe przynajmniej zmniejszają szczegółowość i mogą być używane w tekście.
źródło
jednak widzę, że jest najbardziej preferowany sposób, którego szukałem. Zasadniczo pochodzi z tych odpowiedzi, ale musiałem go zmanipulować, aby był bardziej zbędny i skuteczny .. i myślę, że wszyscy szukają tego, co wymyśliłem
Do momentu::
najpierw uczyń interfejs tak prostym
teraz, aby to wywołanie zwrotne działało, kiedy tylko zechcesz, aby obsłużyć wyniki - bardziej prawdopodobne po wywołaniu asynchronicznym i chcesz uruchomić kilka rzeczy, które zależą od tych reusltów
doSomething
to funkcja, która zajmuje trochę czasu, gdy chcesz dodać do niej callback, aby powiadomić Cię o wynikach, dodaj interfejs wywołania zwrotnego jako parametr do tej metodymam nadzieję, że mój punkt widzenia jest jasny, baw się dobrze
źródło
Jest to bardzo łatwe w Javie 8 z lambdami.
źródło
Pomysł implementacji za pomocą biblioteki reflektów wydał mi się interesujący i wpadłem na pomysł, który moim zdaniem działa całkiem nieźle. Jedyną wadą jest utrata czasu kompilacji sprawdzania, czy przekazujesz prawidłowe parametry.
Używasz tego w ten sposób
źródło
Metoda nie jest (jeszcze) obiektem pierwszej klasy w Javie; nie możesz przekazać wskaźnika funkcji jako wywołania zwrotnego. Zamiast tego utwórz obiekt (który zwykle implementuje interfejs) zawierający potrzebną metodę i przekaż go.
Propozycje zamknięć w Javie - które zapewniłyby zachowanie, którego szukasz - zostały zaproponowane, ale żadna nie zostanie uwzględniona w nadchodzącej wersji Java 7.
źródło
Kiedy potrzebuję tego rodzaju funkcjonalności w Javie, zwykle używam wzorca Observer . Sugeruje dodatkowy obiekt, ale myślę, że jest to prosta droga i jest to szeroko rozumiany wzorzec, który pomaga w czytelności kodu.
źródło
Sprawdź, jak domknięcia zostały zaimplementowane w bibliotece lambdaj. W rzeczywistości zachowują się bardzo podobnie do delegatów C #:
http://code.google.com/p/lambdaj/wiki/Closures
źródło
Próbowałem użyć java.lang.reflect do zaimplementowania 'callback', oto próbka:
źródło
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. wyjście będzienull test: [null]
args[i].getClass()
? Chodzi mi o to, że nie działa, jeśli wybierzesz metodę opartą na typach argumentów. Działa zString.format
czymś innym, co akceptuje, ale może nie działaćnull
.argTypes
tablicę, więc teraz możemy przekazaćnull
argument / parametr bez wystąpienia NullPointerException. Przykładowe dane wyjściowe:NullParameterTest: String parameter=null, int parameter=888
Możesz również zrobić to
Callback
za pomocąDelegate
wzoru:Callback.java
PagerActivity.java
CustomPagerAdapter.java
źródło
Niedawno zacząłem robić coś takiego:
źródło
jest trochę stary, ale mimo wszystko ... Odpowiedź Petera Wilkinsona wydała mi się przyjemna, poza tym, że nie działa dla typów prymitywnych, takich jak int / Integer. Problemem jest na przykład
.getClass()
for theparameters[i]
, który powracajava.lang.Integer
, co z drugiej strony nie zostanie poprawnie zinterpretowane przezgetMethod(methodName,parameters[])
(błąd Javy) ...Połączyłem to z sugestią Daniela Śpiewaka ( w jego odpowiedzi ); kroki do sukcesu obejmowały: wyłapywanie
NoSuchMethodException
->getMethods()
-> szukanie dopasowania jeden pomethod.getName()
->, a następnie jawne przejrzenie listy parametrów i zastosowanie rozwiązania Daniels, takie jak identyfikacja pasujących typów i pasujących sygnatur.źródło
Myślę, że użycie klasy abstrakcyjnej jest bardziej eleganckie, na przykład:
źródło
object
celu „powiadomienie” drugiej osoby,object
gdy wydarzy się coś ważnego, aby druga osobaobject
mogła obsłużyć to zdarzenie. Twojeabstract class
nigdy nie jest oddzielneobject
, jest tylko oddzielneclass
. Używasz tylko jednegoobject
i stajesz się innyclasses
do wykonywania różnych funkcji, co jest istotą polimorfizmu, a nie wzorcem wywołania zwrotnego.Zasadniczo, jeśli chcesz utworzyć obiekt interfejsu, nie jest to możliwe, ponieważ interfejs nie może mieć obiektów.
Opcją jest pozwolić jakiejś klasie zaimplementować interfejs, a następnie wywołać tę funkcję przy użyciu obiektu tej klasy. Ale to podejście jest naprawdę rozwlekłe.
Alternatywnie, napisz new HelloWorld () (* obserwuj, że to jest interfejs, a nie klasa), a następnie zdefiniuj same metody interfejsu. (* Ta definicja jest w rzeczywistości klasą anonimową). Następnie otrzymasz odwołanie do obiektu, za pomocą którego możesz wywołać samą metodę.
źródło
Utwórz interfejs i utwórz tę samą właściwość interfejsu w klasie wywołania zwrotnego.
Teraz w klasie, w której chcesz zostać wywołany, zaimplementuj powyższy utworzony interfejs. a także Przekaż „ten” obiekt / referencję swojej klasy, aby został wywołany z powrotem.
źródło