2011-07-08 17 views
6

Por lo que yo puedo decir, si quiero definir un protocolo (defprotocol) que sólo se pondrá en práctica por uno defrecord, todavía tengo para definir el protocolo primero, y luego definir el defrecord que lo implementa :Combinando Clojure defprotocol y defrecord

(defprotocol AProtocol 
    (a-method [this]) 
    (b-method [this that])) 

(defrecord ARecord [a-field b-field] 
    AProtocol 
    (a-method [this] ...) 
    (b-method [this that] ...)) 

¿No hay forma de combinar los dos, quizás con un protocolo "anónimo"?

+1

¿Hay algún motivo por el que no desee utilizar funciones normales? – Jonas

+0

@Jonas: Es posible que desee refactorizar el protocolo a un 'defprotocol' más tarde para que otros registros puedan implementarlo, pero en este momento, no estoy seguro. Creo que siempre puedo cambiar las funciones ordinarias en funciones de protocolo como parte de la refactorización. Tampoco puedo "anular" una función incorporada como 'count' sin implementar un protocolo, o sombrearé el enlace predeterminado. – Ralph

+1

Una función de protocolo llamada 'count' sombreará también el built-in. – amalloy

Respuesta

11

No haga esto. Un protocolo "privado" o "anónimo" que implementa su registro es simplemente reinventar una versión inútil de OOP en un lenguaje que tiene mejores opciones. Defina una función antigua normal que opera en sus registros; no hay razón para que tenga que estar físicamente unido a ellos.

Si luego desea refaccionarlo para que sea un protocolo ... ¡es fácil! El cliente no podrá notar la diferencia, porque las llamadas a funciones de protocolo se parecen a las llamadas a funciones regulares.

+0

¿Qué sucede si la nueva función es la misma que una función "núcleo" existente? ¿No sombreará la función central? – Ralph

+0

en ese caso, tendría que asignarle un espacio de nombre. my/+ vs + –

+0

@Ralph vea mi comentario sobre su pregunta. Sí, sombreará la función central, pero también usaría un protocolo. Si realmente deseaba que fuera anónimo, podría adjuntar la función como un campo del registro: '(defrecord Foo [count-me]) ... (let [x (Foo. (Constantemente 1))] ... ((: count-me x) x)) ' – amalloy

4

Sí que es completamente correcto :)

La razón principal de esto sería si espera que otros a querer ampliar su protocolo posterior.