12

In Clojure I want to have a protocol where some methods have a default implementation, and some have a custom one. And the first ones refer to the latter ones for configuration. Here is an example:

(defprotocol Saving
  (save [this] "saves to mongodb")
  (collection-name [this] "must return a string representing the associated MongoDB collection"))

;Default implementation

(extend-type Object
  Saving
  ; the `save` method is common for all, so it is actually implemened here
  (save [this] (mc/insert (collection-name [this]) this))
  ; this method is custom to every other type
  (collection-name [this] "no_collection"))

;Particular implementations

(defrecord User
  [login password]
  Saving
  (collection-name [this] "users"))

(defrecord NewsItem
  [text date]
  Saving
  (collection-name [this] "news_items"))

However, it won't work this way. Even though calling collection-name on a User or NewsItem instance returns a correct collection string, calling save on them causes an AbstractMethodError. How can I acheive this trivial OO-shaped goal with Clojure?

0

1 Answer 1

15

Make the save function a normal function:

(defn save [obj] (mc/insert (collection-name obj) obj))

The protocol should only have collection-name

(defprotocol Saving
  (collection-name [this] "must return a string representing the associated MongoDB collection"))

And then each object that wants to be "saved" can implement this protocol.

Remember: OO style often hide the obvious simple thing :)

Sign up to request clarification or add additional context in comments.

1 Comment

I have a similar question to do this: I want an abstract protocol method and an a defaulted alias for it with identical functionality. The alias would simply call the abstract method. The reason for the alias is to provide Java caller-friendly name. Can I achieve this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.