पैकेज ऑब्जेक्ट्स


92

पैकेज ऑब्जेक्ट क्या हैं, इतनी अवधारणा नहीं बल्कि उनका उपयोग?

मैंने काम करने के लिए एक उदाहरण प्राप्त करने की कोशिश की है और मुझे जो एकमात्र रूप काम करने के लिए मिला वह इस प्रकार है:

package object investigations {
    val PackageObjectVal = "A package object val"
}

package investigations {

    object PackageObjectTest {
        def main(args: Array[String]) {
            println("Referencing a package object val: " + PackageObjectVal)
        }
    }
}

अब तक मैंने जो अवलोकन किए हैं, वे हैं:

package object _root_ { ... }

अस्वीकृत है (जो उचित है),

package object x.y { ... }

भी अस्वीकृत है।

ऐसा लगता है कि तत्काल मूल पैकेज में एक पैकेज ऑब्जेक्ट घोषित किया जाना चाहिए और, यदि ऊपर लिखा गया है, ब्रेस सीमांकित पैकेज घोषणा फॉर्म की आवश्यकता है।

क्या वे आम उपयोग में हैं? यदि हां, तो कैसे?



1
@Brent, यह एक बेहतरीन संसाधन है, न कि केवल पैकेज ऑब्जेक्ट लेख के लिए। मैंने लेखक के बारे में सुना है, लेकिन यह महसूस नहीं किया कि उसने इस स्काला दौरे को लिखा है, धन्यवाद।
डॉन मैकेंजी

जवाबों:


128

आम तौर पर आप अपनी पैकेज वस्तु को एक अलग फाइल में रखते हैं जिसे package.scalaपैकेज में कहा जाता है। आप नेस्टेड पैकेज सिंटैक्स का भी उपयोग कर सकते हैं लेकिन यह काफी असामान्य है।

पैकेज ऑब्जेक्ट के लिए मुख्य उपयोग मामला तब होता है जब आपको पैकेज द्वारा परिभाषित एपीआई का उपयोग करते समय पैकेज के बाहर और साथ ही पैकेज के अंदर विभिन्न स्थानों में परिभाषाओं की आवश्यकता होती है। यहाँ एक उदाहरण है:

// file: foo/bar/package.scala

package foo

package object bar {

  // package wide constants:
  def BarVersionString = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // can be used to emulate a package wide import
  // especially useful when wrapping a Java API
  type DateTime = org.joda.time.DateTime

  type JList[T] = java.util.List[T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}

अब उस पैकेज ऑब्जेक्ट के अंदर की परिभाषाएँ पूरे पैकेज के अंदर उपलब्ध हैं foo.bar। इसके अलावा परिभाषाएँ आयातित हो जाती हैं जब कोई उस पैकेज के बाहर आयात करता है foo.bar._

इस तरह से आप अपने क्लायंट को प्रभावी ढंग से उपयोग करने के लिए अतिरिक्त आयात जारी करने के लिए एपीआई क्लाइंट की आवश्यकता को रोक सकते हैं - उदाहरण के लिए स्केला-स्विंग में आपको लिखना होगा

import swing._
import Swing._

की तरह सभी अच्छाई onEDTऔर अंतर्निहित रूपांतरणों के Tuple2लिए Dimension


13
शब्द का सावधानी: विधि अधिभार पैकेज वस्तुओं में काम नहीं करता है।
रेट्रानिक

मुझे मारता है कि क्यों चुना गया था कि पैकेज ऑब्जेक्ट को पैकेज पदानुक्रम तक एक स्तर परिभाषित किया जाना चाहिए। उदाहरण के लिए इसका मतलब है कि आपको अपने पैकेज ऑब्जेक्ट के साथ आभासी orgया comशीर्ष स्तर के पैकेज को प्रदूषित करने की आवश्यकता है यदि आप इसके लिए अपने स्वयं के रूट पैकेज जैसे हैं org.foo। मुझे लगता है कि परिभाषा को सीधे पैकेज के तहत होने की अनुमति देना - इसका एक हिस्सा होना चाहिए - थोड़ा और उचित भाषा एपीआई इंटरफ़ेस होता।
Matanster

58

जबकि मोरित्ज़ का जवाब हाजिर है, एक और ध्यान देने वाली बात यह है कि पैकेज ऑब्जेक्ट्स ऑब्जेक्ट हैं। अन्य बातों के अलावा, इसका मतलब है कि आप उन्हें मिक्स-इन इनहेरिटेंस का उपयोग करते हुए लक्षणों से बना सकते हैं। मोरिट्ज़ के उदाहरण के रूप में लिखा जा सकता है

package object bar extends Versioning 
                          with JodaAliases 
                          with JavaAliases {

  // package wide constants:
  override val version = "1.0"

  // or type aliases
  type StringMap[+T] = Map[String,T]

  // Define implicits needed to effectively use your API:
  implicit def a2b(a: A): B = // ...

}

यहां वर्जनिंग एक अमूर्त विशेषता है, जो कहती है कि पैकेज ऑब्जेक्ट में एक "संस्करण" विधि होनी चाहिए, जबकि JodaAliases और JavaAliases ठोस लक्षण होते हैं जिनमें आसान प्रकार के उपनाम होते हैं। इन सभी लक्षणों को कई अलग-अलग पैकेज ऑब्जेक्ट द्वारा पुन: उपयोग किया जा सकता है।


पूरा विषय बहुत खुल रहा है और ऐसा लगता है कि इसका उपयोग पूरी क्षमता से किया जा रहा है, एक और समृद्ध उदाहरण के लिए धन्यवाद।
डॉन मैकेंजी

1
लेकिन वे
घाटी के

7

आप सीधे स्रोत पर जाने की तुलना में बदतर कर सकते हैं। :)

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/package.scala

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/collection/immutable/package.scala


@Alex क्रूज़, धन्यवाद, यह सुझाव देता है कि उन्हें एक अलग संकलन इकाई की आवश्यकता है (जो संभवतः ब्रेस सीमांकित पैकेज प्रतिबंध को पूरा करता है)। समस्या यह है कि मैं कैसे उपयोग करने के बारे में अपने अनुमान के बजाय कुछ ठोस उपयोगकर्ता सलाह चाहता हूं।
डॉन मैकेंजी

5

पैकेज ऑब्जेक्ट के लिए मुख्य उपयोग मामला तब होता है जब आपको पैकेज द्वारा परिभाषित एपीआई का उपयोग करते समय पैकेज के बाहर और साथ ही पैकेज के अंदर विभिन्न स्थानों में परिभाषाओं की आवश्यकता होती है।

ऐसा नहीं है, स्काला 3 के साथ , डोट्टी के आधार पर , 2020 के मध्य में रिलीज़ होने वाली है , जैसा कि यहाँ है :

टॉपलेवल परिभाषाएँ

सभी प्रकार की परिभाषाएँ टॉपवेल पर लिखी जा सकती हैं।
पैकेज ऑब्जेक्ट्स की अब आवश्यकता नहीं है, चरणबद्ध किया जाएगा।

package p 

type Labelled[T] = (String, T) 
val a: Labelled[Int] = ("count", 1) 
def b = a._2 
def hello(name: String) = println(i"hello, $name)

धन्यवाद @VonC, मैं वास्तव में इस और कई अन्य कारणों के लिए स्काला 3 का इंतजार कर रहा हूं। मैंने पैकेज ऑब्जेक्ट का अधिक उपयोग नहीं किया है, लेकिन मुझे यकीन है कि मैं शीर्ष स्तर की परिभाषाओं का उपयोग करूंगा।
डॉन मैकेंजी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.