2015-08-30 5 views
12

Al momento, ho una libreria Clojure completamente funzionale che viene chiamata da Java.Creazione di una libreria di protocolli e defrecords per l'utilizzo da Java

Il modo in cui faccio questo: ho un file che utilizza gen-class per avvolgere l'intera API come metodi statici di una singola classe e passa i dati in entrata e in uscita sotto forma di IPersistentVector e IPersistentMap.

Ora, tuttavia, sto rifattorizzando la libreria e inserendo le funzionalità dietro vari protocolli.

ho quattro protocolli, immobili chiamarli A, B, C e D. E due defrecords, X e Y. X e Y sia implementare protocolli A, B e C. Mentre Y implementa anche D.

Cosa devo fare per renderli disponibili su Java? Sono automaticamente disponibili come interfacce e classi? O devo ancora fare l'equivalente della classe gen per renderli pubblici?

In caso contrario, qual è l'equivalente della clausola gen: class, dove definisco i tipi Java per gli argomenti dei metodi?

Qualcuno ha un semplice esempio di rendere disponibili protocolli e record su Java?

risposta

6

defprotocol

Ogni protocollo Clojure è anche un'interfaccia Java con lo stesso nome e metodi. Se prendo un esempio da ibm developerworks, vediamo che:

(ns com.amalgamated) 

(defprotocol Fulfillment 
    (invoice [this] "Returns an invoice") 
    (manifest [this] "Returns a shipping manifest")) 

è equivalente a:

package com.amalgamated; 

public interface Fulfillment { 
    public Object invoice(); 
    public Object manifest(); 
} 

Clojure.org ha anche alcune informazioni (piuttosto laconico) su questo.

Un client Java che desidera partecipare al protocollo può farlo in modo efficace la maggior parte dello implementando l'interfaccia generata dal protocollo. Esterni implementazioni del protocollo (che sono necessari quando si desidera una classe o digitato non nel controllo di partecipare al protocollo) può essere forniti utilizzando il costrutto estendere:

(extend AType AProtocol 
{:foo an-existing-fn 
    :bar (fn [a b] ...) 
    :baz (fn ([a]...) ([a b] ...)...)} BProtocol 
    {...} ...) 

definterface

Se si punta alla performance, è possibile considerare l'utilizzo di definterface, che è simile ai protocolli. Questo SO post ha anche dettagli su come usarlo:

(definterface Foo 
    [^int foo [x ^String y]] 
    [^void bar [^ints is]]) 

definterface sembrano essere faster di protocolli.

defrecord

Allo stesso modo, record s (così come deftype e definterface) genereranno classi Java. Anche in questo caso, Clojure.org/datatypes ha informazioni utili (sottolineatura mia):

DEFTYPE e defrecord generare dinamicamente bytecode compilato per un nome classe con una serie di dati campi, e, opzionalmente, metodi per uno o più protocolli e/o interfacce. Sono adatti per lo sviluppo dinamico e lo sviluppo interattivo, non deve essere compilato AOT, e può essere rivalutato nel corso di una singola sessione. Sono simili a defstruct nella generazione di strutture di dati con campi di nome, ma si differenziano da defstruct in che: [...]

Quindi sì, se sarà disponibile da Java. Basta fare attenzione con i nomi.

Come nota a margine, si consiglia di dare un'occhiata a calling Clojure from Java.

Problemi correlati