definterface

added
1.2

ns
clojure.core

type
macro

(definterface name & sigs)

Creates a new Java interface with the given name and method sigs.
The method return types and parameter types may be specified with type hints,
defaulting to Object if omitted.

(definterface MyInterface
(^int method1 [x])
(^Bar method2 [^Baz b ^Quux q]))

                ;; Part of a definterface from a Clojure program for the n-body problem
;; at the Computer Language Benchmarks Game web site.
;; For the rest of the program using it, see:
;; http://github.com/jafingerhut/clojure-benchmarks/blob/master/nbody/nbody.clj-14.clj

;; Currently Clojure does not permit type hints of arrays, e.g. ^ints as
;; argument types or return types in a definterface.  This may be enhanced
;; later.

(definterface IBody
  (^String name [])  ;; return type String, no arguments
  (^double mass [])  ;; return type double
  (^double x [])
  (clone [] "returns copy of self")   ; return type defaults to ^Object
  ;; 3 arguments of type double.  A deftype that implements this interface
  ;; must implement the method p!  The definterface must use:
  ;; _BANG_ for ! in Clojure method name
  ;; _PLUS_ for +
  ;; _ for -
  (p_BANG_ [^double x ^double y ^double z] "set pos.")
  ;; After name demangling, this must be implemented by Clojure method named v+!
  (v_PLUS__BANG_ [^double vx ^double vy ^double vz] "add to velocity"))

            
                ;; Note these differences between defprotocol and definterface:

;; defprotocol requires that methods specify a first parameter, which 
;; will be the record object, while definterface requires that this
;; parameter be left out:
(definterface I (fooey []))
;=> user.I
(defprotocol P (fooey []))
;=> IllegalArgumentException Definition of function fooey in protocol P must take at least one arg.  clojure.core/emit-protocol/fn--5964 (core_deftype.clj:612)
(defprotocol P (fooey [this]))
;=> P

;; However, defrecord requires that a parameter for the record object
;; be used, even with interfaces.  (A similar point applies to deftype.)
(defrecord Irec [stuff] I (fooey [] "foo"))
;=> CompilerException java.lang.IllegalArgumentException: Must supply at least one argument for 'this' in: fooey, compiling:(NO_SOURCE_PATH:1:1) 
(defrecord Irec [stuff] I (fooey [this] "foo"))
;=> user.Irec
(defrecord Prec [stuff] P (fooey [this] "foo"))
;=> user.Prec

;; Using an interface, only the dot form of the method is available with 
;; defrecord, while the protocol also allows use of normal Clojure function
;; syntax.  (Similar points apply to deftype.)
(.fooey (Irec. 42))
;=> "foo"
(fooey (Irec. 42))
;=> IllegalArgumentException No implementation of method: :fooey of protocol: #'user/P found for class: user.Irec  clojure.core/-cache-protocol-fn (core_deftype.clj:544)
(.fooey (Prec. 42))
;=> "foo"
(fooey (Prec. 42))
;=> "foo"