Whats the rationale behind closed records in Clojure?

Viewed 1152

I have the option of directly implementing a Protocol in the body of a defrecord instead of using extend-protocol/extend-type

(defprotocol Fly
  (fly [this]))

(defrecord Bird [name]
  Fly
  (fly [this] (format "%s flies" name)))

=>(fly (Bird. "crow"))
"crow flies"

If I now try to override the Fly protocol, I get an error

(extend-type Bird
  Fly
  (fly [this] (format "%s flies away (:name this)))

class user.Bird already directly implements interface user.Fly for protocol:#'user/Fly

On the other hand if instead I use extend-type initially

(defrecord Dragon [color])

(extend-type Dragon
  Fly
  (fly [this] (format "%s dragon flies" (:color this))))

=>(fly (Dragon. "Red"))
"Red dragon flies"

I can then "override" the the fly function

(extend-type Dragon
  Fly
  (fly [this] (format "%s dragon flies away" (:color this))))

=>(fly (Dragon. "Blue"))
"Blue dragon flies away"

My question is, why not allow extension in both cases? Is this a JVM limitation because of the Record <-> Class relation or is there a use case for a non overridable protocol?

1 Answers
Related