Możesz zajrzeć do adaptera Ring's Jetty na przykładzie wdrożenia serwletu w Clojure. Źródło jest dostępne here (link do źródła wydania 1.1). W szczególności pierwsza funkcja zdefiniowana w tej przestrzeni nazw, proxy-handler
zwraca procedurę obsługi na podstawie abstrakcyjnej klasy udostępnionej przez Jetty.
Jeśli zdecydujesz się wdrożyć podobne podejście (opierając serwlet na klasie Java zapewniającej pewną gotową metodę implikuje), musisz użyć proxy
; jeśli potrzebujesz tylko implementować interfejsy (bez podklasy), prawdopodobnie będziesz potrzebował reify
zamiast tego. To, czy makra będą użyteczne, zależy od tego, które części implementacji okażą się poprawne; Adapter Rdzeń pierścienia nie skorzystałby z użycia makr, ale możesz (na przykład, jeśli chcesz rozszerzyć klasę/interfejs na implementację do argumentu, co wydaje się wskazywać pytanie).
W każdym przypadku dowolna funkcja wybrana do wdrożenia będzie musiała być częścią interfejsu lub protokołu. Tak, wdrażanie javax.servlet.Servlet
plus dodatkowe działanie foo
może wyglądać następująco:
(import (javax.servlet Servlet ServletRequest ServletResponse))
(defprotocol PFoo
(foo [this x y z]))
(reify
Servlet
(service [this ^ServletRequest req ^ServletResponse res]
...)
;; other Servlet methods here...
PFoo
(foo [this x y z]
...))
Można następnie owinąć to w makro dostarczyć dowolny cukier syntaktyczny. Zauważ, że reify
rzeczywistości nie dbają o sposób, w którym przeplatać interfejsu/nazwy i definicje protokołów metoda wewnątrz swojego ciała, więc można mieć makra emitować
(reify
Servlet PFoo ... ; other interfaces & protocols
(service [...] ...)
(foo [...] ...)
;; other methods
)
jeśli jest to bardziej wygodne.
Szkic makro przy nazwę interfejsu serwletów wdrożyć (przypuszczalnie rozszerzenie javax.servlet.Servlet
) oraz wtryskiwanie protokół z dodatkowymi sposobami:
(defprotocol PFancyServlet
(do-get [this ...])
(do-post [this ...]))
(defmacro servlet [servlet-iface & meths]
`(reify ~servlet-iface PFancyServlet
[email protected]))
meths
powinien zawierać do-get
i do-post
jak servlet-iface
metody; możesz dodać argumentację, aby upewnić się, że tak właśnie jest. Przykładowa rozmowa:
(servlet SomeServletInterface
(service [this ...] ...)
;; ...
(do-get [this ...] ...)
(do-post [this ...] ...))
Awesome! Jak mogę mieć funkcje bez "tego" jako pierwszego parametru? (servlet IndexServlet (do-get [request response])) – Chiron
Może zajść potrzeba użycia 'this' w ciałach metod (jeśli metody wywołują się nawzajem, powiedzmy). To powiedziawszy, twoje makro może wstępnie przetwarzać 'mets' w arbitralny sposób, w szczególności dodając' this' z powrotem, jeśli pominiesz go w składni na poziomie użytkownika: '(niech [[nazwa-meta-params & body] meth] \' (~ nazwa-mety ~ (vec (cons 'this params)) ~ @ body)) 'lub coś podobnego. To spowodowałoby rozszerzenie, w którym "ten" byłby dostępny jako "magiczny parametr" w każdej z ciał metod. Lub możesz użyć '(gensym" this __ ")' zamiast ''this' w rozszerzeniu, aby" ukryć "' this', jeśli tego chcesz. –
Również 'proxy' czyni już' ten' niejawnym (zobacz '(doc proxy)'), podobnie jak 'definterface',' gen-interface' i 'gen-class'; 'reify',' deftype', 'defrecord',' defprotocol' nie. (Odp: 'klasa genów', to deklaracje metod w" klasie genów ", które pomijają" to ", funkcje implementujące muszą to wyraźnie zaznaczyć). –