2011-09-09 8 views
8

मेरे पास कुछ कोड है जिसमें इस बात का आविष्कार है कि उस वस्तु में एक वस्तु का निर्माण किया जाना चाहिए जहां अंततः इसका उपयोग किया जाता है (वैश्विक राज्य से संबंधित विभिन्न कारणों से जो आदर्श नहीं हैं लेकिन कुछ हिस्सा हैं धारणा का)।कंस्ट्रक्टर कॉल के स्थान के लिए स्कैला संकलन समय की जांच

उदा। मान लीजिए कि नीचे फंक्शन बू है जो म्यू में हेरफेर करने के लिए ज़िम्मेदार है।

def boo(mooGen:() => Moo) { 
    val m = mooGen() // a new MOO must be created HERE 
    m.moo() 
} 

बू के ग्राहकों कि बू उपयोग करना चाहते हैं() => मू, जहां समारोह उत्पन्न करता वांछित मू एक प्रकार में से गुजरना होगा।

आदर्श ग्राहक व्यवहार:

boo(() => new Moo(// specific parameters here)) 
मू

बू शरीर के अंदर तक नहीं बनाया गया है।

हालांकि, एक ग्राहक आसानी से निम्न कोड के साथ गलत कदम कर सकते हैं:

val myMoo = new Moo(// specific parameters here) 
boo(() => myMoo) 

यह अपरिवर्तनीय है जहाँ हम मू निर्माण केवल बू में होते देखना चाहते टूट जाता है।

तो मूल रूप से, मैं यह निर्धारित करना चाहता हूं कि फ़ंक्शन के कॉल स्टैक के भीतर mooGen का वापसी मूल्य बनाया गया है या फिर इसे पहले से बनाया गया था या नहीं।

रनटाइम पर इसे सत्यापित करने के कई तरीके हैं। हालांकि, संकलन समय पर इस पैटर्न को मजबूर करने का कोई तरीका है? Implicits या कुछ और चालाक का उपयोग कर?

किसी भी विचार की सराहना की जाती है!

उत्तर

12

बोओ और म्यू को अपने स्वयं के ऑब्जेक्ट में रखो, साथ में टोकन क्लास के साथ, जिसे ऑब्जेक्ट के बाहर तत्काल नहीं किया जा सकता है।

scala> object Foo { 
    | class Moo(token:Token) {} 
    | class Token private[Foo]() 
    | def boo(mooGen: (Token) => Moo) {val m = mooGen(new Token)} 
    | } 
defined module Foo 

आप अब क्या चाहते किया जा सकता है:

scala> Foo.boo(new Foo.Moo(_)) 

और तुम नहीं चाहते कि क्या नहीं किया जा सकता:

scala> val mymoo = new Foo.Moo(new Foo.Token) 
<console>:8: error: constructor Token in class Token cannot be accessed in objec 
t $iw 
     val mymoo = new Foo.Moo(new Foo.Token) 
         ^

लेकिन अगर ग्राहक वास्तव में चाहता है दुर्भाग्यवश - वह अभी भी अपना म्यू प्राप्त कर सकता है:

val ireallywantone = new Foo.Moo(null.asInstanceOf[Foo.Token]) 
3

मुझे लगता है कि अगर दोनों Moo के निर्माता और विधि boo अपने नियंत्रण में हैं, और, तो आप Moo एक अंतर्निहित पैरामीटर कर सकते हैं और व्यवस्था ग्राहकों द्वारा लिखे जाने की जरूरत नहीं है कि केवल जगह है कि एक उपयुक्त अंतर्निहित मूल्य दायरे में है boo में है।

यह आदर्श नहीं है ... और आप अंतर्निहित पैरामीटर का प्रकार पूरी तरह से निजी बनाने में सक्षम नहीं हो सकते हैं (जो इसे और अधिक निश्चित कर देगा कि क्लाइंट boo के बाहर तत्काल नहीं करता है), क्योंकि मुझे संदेह है कि संकलक Moo की परिभाषा में एक निजी प्रकार के लीकिंग के बारे में शिकायत करेगा। लेकिन इसके बिना भी, कम से कम आकस्मिकMoo के boo के बाहर आपको रोकने में मदद करनी चाहिए; ग्राहक को जानबूझकर एक Moo बनाने की अनुमति देने के लिए एक अंतर्निहित मूल्य प्राप्त करना होगा।

संबंधित मुद्दे