2011-12-23 14 views
15

में जावा इंटरफ़ेस को मैं कैसे कार्यान्वित करूं? मैं क्लोजर ऑब्जेक्ट कैसे बना सकता हूं जो इस इंटरफ़ेस को लागू करता है और फिर जावा कोड से कॉल किया जाता है?क्लोजर

public interface Doer { 
    public String doSomethin(String input); 
} 

Doer clojureDoer = ?; 

String output = clojureDoer.doSomethin(input); 
+0

धन्यवाद:

(ns my.clojure.namespace (:import [my.java.package Doer])) (defn reify-doer "Some docstring about what this specific implementation of Doer does differently than the other ones. For example, this one does not actually do anything but print the given string to stdout." [] (reify Doer (doSomethin [this in] (println in)))) 

तो जावा से, है, आप इसे इस रूप में यहां पहुंच सकता है मेरी मदद करने के लिए हर कोई! मैं Reify का उपयोग कर समाप्त हो गया और क्लोजर में मुख्य समारोह लिखा था। क्लोजर अविश्वसनीय रूप से अच्छा है! –

उत्तर

41

reify दृढ़ता से इंटरफेस को लागू करने के लिए पसंद किया जाता है में जावा से इस्तेमाल किया जा रहा - proxy हेवी-ड्यूटी, वर्ष, और धीमी गति से है, इसलिए जब संभव बचा जाना चाहिए। एक कार्यान्वयन लगेगा जैसे:

(reify Doer 
    (doSomethin [this input] 
    (...whatever...))) 

ध्यान दें कि proxy उपयोग के बारे में मौजूदा जवाब, गलत वाक्यविन्यास है अगर तुम सब के बाद एक प्रॉक्सी के साथ जाने का निर्णय: प्रॉक्सी एक अंतर्निहित this तर्क है, न कि नामित पहला तर्क लेता है।

+0

कूल। फिर जावा से clojureDoer ऑब्जेक्ट को कॉल करना संभव है? –

+4

मेरे उत्तर में हमारी गलती को इंगित करने के लिए धन्यवाद। यदि आप इसे मेरे उत्तर के तहत एक टिप्पणी के रूप में जोड़ना चाहते हैं, तो यह अधिक उपयोगी होगा। चीयर्स! – Jan

12

प्रॉक्सी

साथ proxy मैक्रो देखें। Clojure Docs कुछ उदाहरण हैं। यह Java Interop पृष्ठ पर भी शामिल है।

(proxy [Doer] [] 
    (doSomethin [input] 
    (str input " went through proxy"))) 

proxy एक वस्तु Doer को लागू करने देता है। अब, जावा में इसे एक्सेस करने के लिए आपको अपने क्लोजर कोड को जावा से कॉल करने योग्य बनाने के लिए gen-class का उपयोग करना होगा। यह "Calling clojure from java" प्रश्न के उत्तर में शामिल है।

जनरल स्तर के साथ

(ns doer-clj 
    (:gen-class 
    :name DoerClj 
    :implements [Doer] 
    :methods [[doSomethin [String] String]])) 

(defn -doSomethin 
    [_ input] 
    (str input " went through Clojure")) 

अब doer_clj.clj, mkdir classes के रूप में सहेज और अपने आरईपीएल (require 'doer-clj) (compile 'doer-clj) में फोन करके यह संकलन। आपको पता होना चाहिए DoerClj.class तैयार classes निर्देशिका

+0

नोट "डोर क्लोजर डूअर =?" मेरे प्रश्न में मैं "?" में क्या डालूं कार्यक्रम को काम करने के लिए। आपके द्वारा दिया गया लिंक दिखाता है कि स्थैतिक वर्ग के रूप में क्लोजर ऑब्जेक्ट को कैसे आयात किया जाए। धन्यवाद! –

+0

ऐसे मामले में आप मेरे उत्तर के दूसरे भाग में अधिक दिलचस्पी ले सकते हैं जिसे मैंने अभी जोड़ा है। यह 'प्रॉक्सी' मुक्त है और आपके मामले के लिए रास्ता अधिक उचित लगता है। मुझे लगता है कि अगर दूसरा आपकी समस्या हल करता है तो मैं पहली छमाही हटा दूंगा। – Jan

+0

दिलचस्प .. मुझे डोर को एक पैकेज में रखना पड़ा, क्योंकि संकलक java.lang.Doer की तलाश में था। मुझे थ्रेड "मुख्य" java.lang में अपवाद अपवाद मिला।ClassFormatError: जब मैं कर्ता करता हूं DoerCler = new DoerClj(); क्लास फ़ाइल में डुप्लिकेट विधि का नाम और हस्ताक्षर DoerClj –

7

इस प्रश्न पर एक अधिक सामान्य ले लिए, इस चित्र उपयोगी गुस्सा किया जा सकता है जब आप जावा इंटरॉप किसी तरह के लिए की जरूरत में हैं:

https://github.com/cemerick/clojure-type-selection-flowchart

+0

मैं उस समय एक बार पहले भाग गया, लेकिन मुझे एहसास नहीं हुआ कि यह वास्तव में संसाधन का कितना अच्छा है। यह बात बताने के लिए धन्यवाद। – Bill

0

तो doSomethin() अपने इंटरफ़ेस में परिभाषित किया गया है, तो आप :methods में इसका उल्लेख करना चाहिए। http://clojuredocs.org/clojure_core/clojure.core/gen-class से उद्धरण:

:methods [ [name [param-types] return-type], ...] 
The generated class automatically defines all of the non-private 
methods of its superclasses/interfaces. This parameter can be used 
to specify the signatures of additional methods of the generated 
class. Static methods can be specified with ^{:static true} in the 
signature's metadata. Do not repeat superclass/interface signatures 
here. 
13

Clojure 1.6 के रूप में, वरीय दृष्टिकोण इस प्रकार होगा। मान लें कि आप अपने classpath, Clojure 1.6 जार और निम्नलिखित clojure फ़ाइल (या इसके संकलित समकक्ष) पर है,:

package my.other.java.package.or.maybe.the.same.one; 

import my.java.package.Doer; 
import clojure.lang.IFn; 
import clojure.java.api.Clojure; 

public class ClojureDoerUser { 
    // First, we need to instruct the JVM to compile/load our 
    // Clojure namespace. This should, obviously, only be done once. 
    static { 
     IFn require = Clojure.var("clojure.core", "require"); 
     require.invoke(Clojure.read("my.clojure.namespace")); 
     // Clojure.var() does a somewhat expensive lookup; if we had more than 
     // one Clojure namespace to load, so as a general rule its result should 
     // always be saved into a variable. 
     // The call to Clojure.read is necessary because require expects a Clojure 
     // Symbol, for which there is no more direct official Clojure API. 
    } 

    // We can now lookup the function we want from our Clojure namespace. 
    private static IFn doerFactory = Clojure.var("my.clojure.namespace", "reify-doer"); 

    // Optionally, we can wrap the doerFactory IFn into a Java wrapper, 
    // to isolate the rest of the code from our Clojure dependency. 
    // And from the need to typecast, as IFn.invoke() returns Object. 
    public static Doer createDoer() { 
     return (Doer) doerFactory.invoke(); 
    } 
    public static void main(String[] args) { 
     Doer doer = (Doer) doerFactory.invoke(); 
     doer.doSomethin("hello, world"); 
    } 
} 
+0

धन्यवाद @ गैरी वेरहेजेन;) –