Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can you implement interfaces with defrecord #8

Closed
gdavis-github opened this issue Apr 11, 2014 · 7 comments
Closed

can you implement interfaces with defrecord #8

gdavis-github opened this issue Apr 11, 2014 · 7 comments

Comments

@gdavis-github
Copy link

Sorry if this is out of place, because I'm one of the newbies trying to use your great chart.

Should there be a path
from:
"Will the type need to extend a Java class or implement any interfaces?"
to:
"Use defrecord"

I can't figure out a way to add interfaces using defrecord. Could it be that the decision:
"Do you need to be able to refer to the class statically from Java?"
needs to be at a different point, since it steers you back to deftype/defrecord?

@cemerick
Copy link
Owner

You can get from the former to the latter, but it necessitates a trip through the "interop zone" to eliminate any reasons why you'd have to fall back on gen-class.

You can't define interfaces using defrecord; it always defines a class, which may implement Java interfaces.

If you're looking to define an interface, look at the (undocumented) definterface. There's some usage of it here. Or, just define the interface in Java; it's really quite sane for doing that, and allows you to provide e.g. documentation for non-Clojure consumers of your interface.

@gdavis-github
Copy link
Author

At the risk of seeming pre-newbie... When I try:

(defrecord Rec0 [x])
(extend-type Rec0 clojure.lang.IHashEq (hasheq [this] 5))

I get an
"IllegalArgumentException infterace clojure.lang.IHashEq is not a protocol"
so it seems that while protocols create interfaces, interfaces are not necessarily protocols.

I guess what I'm saying is I can't figure out how to implement an interface with defrecord, which is the subject of the initial question.

@cemerick
Copy link
Owner

You're right, protocols expose an interface, but interfaces are certainly not all protocols. Protocols are a Clojure construct, not a JVM one.

I'd suggest you take a look at some introductory materials (http://clojurebook.com if I may be so bold), or the standard documentation and examples that are here and there online.

@gdavis-github
Copy link
Author

I've been scouring the standard documentation and examples. It's not bold at all to suggest your book. My investment so far have been 'The Joy of Clojure' and 'Clojure in Action'. I just got your book from O'Reilly.

From the documentation and the example above, I now don't think I can implement a non-protocol JVM interface on deftype or defrecord, but the flowchart suggests that I can.

The path I follow is:
"Will the type need to extend a Java class or implement any interfaces?" - Yes, IHashEq
"Do you need a named type or only an instance of an anonymous type?" - Named type
"Do you need to be able to refer to the class statically from Java" - No
"Is your class modeling a domain value -- thus ... semantics?" - Yes
"Use defrecord"

Am I mistaken in my understanding of the documentation, or in following the flowchart?

@gdavis-github
Copy link
Author

Great! Your book took me directly to the solution. Add the JVM interface to the protocol with #'extend-protocol.

Perhaps this could be a notation on the flowchart?

@cemerick
Copy link
Owner

No, you can absolutely implement any JVM interface for deftype or defrecord, just not with extend-protocol. One of the links I provided earlier has examples of doing this, as does Clojure Programming.

Extending a protocol to an interface can be questionable, and not something I want to encourage by documenting it.

@gdavis-github
Copy link
Author

Apologies. Your book's example in "Participating in Clojure's Collection Abstractions" of Chapter 6, with (deftype ArraySet ...) is the perfect example for me.

My earlier comment was made before comprehension took hold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants