स्विफ्ट में Namespaces का उपयोग कैसे करें?


144

दस्तावेज़ में केवल नेस्टेड प्रकारों का उल्लेख है, लेकिन यह स्पष्ट नहीं है कि क्या उन्हें नामस्थान के रूप में उपयोग किया जा सकता है। मुझे नामस्थानों का कोई स्पष्ट उल्लेख नहीं मिला है।


उनके iBook की त्वरित Ctrl-F खोज नामस्थानों का कोई उदाहरण नहीं दिखाती है ... इसलिए मैं नहीं के साथ जा रहा हूं?
जस्टिन निस्नर

1
मुझे नहीं पता कि यह सवाल बंद क्यों है। मैंने स्विफ्ट आइकन के बाईं ओर मुख्य वक्ता के रूप में नामस्थान देखा , और मुझे अभी भी प्रलेखन से कोई उल्लेख नहीं मिल रहा है ...
eonil

मुझे इस बारे में कोई जानकारी नहीं मिली, Google ने मुझे इस सवाल की ओर बढ़ाया :)। शायद WWDC सत्रों में से एक इस पर थोड़ा और प्रकाश डालेगा।
ज्यफ्रैक्स

मैं भी WWDC में किसी के लिए अच्छी व्याख्या के साथ आने का इंतजार कर रहा हूं।
eonil

Eonil का उत्तर सही है। आप अपनी कक्षाओं को अलग करने के लिए Xcode में मॉड्यूल का उपयोग करते हैं।
ज्येफ्राक्स

जवाबों:


113

Apple देव फोरम में सेवनटेलेवेन द्वारा उत्तर दिया गया :

नाम-स्थान प्रति-फ़ाइल नहीं हैं; वे प्रति-लक्ष्य ("उत्पाद मॉड्यूल नाम" बिल्ड सेटिंग के आधार पर) हैं। तो आप कुछ इस तरह से समाप्त करेंगे:

import FrameworkA
import FrameworkB

FrameworkA.foo()

सभी स्विफ्ट घोषणाओं को कुछ मॉड्यूल का हिस्सा माना जाता है, इसलिए जब आप कहते हैं कि " NSLog" (हाँ, यह अभी भी मौजूद है) तो आपको स्विफ्ट के बारे में " Foundation.NSLog" जैसा लगता है ।

साथ ही क्रिस लैटनर ने नेमस्पेसिंग के बारे में ट्वीट किया

Namespacing स्विफ्ट में निहित है, सभी वर्गों (आदि) वे मॉड्यूल (Xcode लक्ष्य) द्वारा स्पष्ट रूप से scoped हैं वे में हैं। कोई वर्ग उपसर्ग की जरूरत नहीं है।

बहुत अलग लगता है कि मैं क्या सोच रहा था।


6
Apple देव मंचों ... मैंने देखा है कि आप विश्वास नहीं करेंगे!
निकोलस मिआरी

1
Apple देव मंचों का लिंक अब टूट गया है, और Apple ने forums.developer.apple.comदुर्भाग्य से, नए मंचों में उस धागे को आयात नहीं किया है ।
दाई

2
@Dai ऐसा लगता है कि हमें क्यू एंड ए के लिए Apple मंचों से बचना चाहिए ... लेकिन कोर देव टीम के सदस्यों को SO पर ज्यादा ध्यान नहीं लगता है। क्या त्रासदी है।
eonil

1
तुम्हारा मतलब क्या है?
अलेक्जेंडर मिल्स

148

मैं स्विफ्ट के नामकरण को आकांक्षा के रूप में वर्णित करूंगा; इसे बहुत सारे विज्ञापन दिए गए हैं जो जमीन पर किसी भी सार्थक वास्तविकता के अनुरूप नहीं हैं।

उदाहरण के लिए, WWDC वीडियो बताता है कि यदि आप जो फ्रेमवर्क आयात कर रहे हैं, उसमें एक वर्ग MyClass है और आपके कोड में एक वर्ग MyClass है, तो वे नाम संघर्ष नहीं करते हैं क्योंकि "name mangling" उन्हें अलग आंतरिक नाम देता है। वास्तव में, हालांकि, वे संघर्ष करते हैं, इस अर्थ में कि आपका अपना कोड MyClass जीतता है, और आप निर्दिष्ट नहीं कर सकते "नहीं नहीं, मेरा मतलब फ्रेमवर्क में MyClass" है - यह कहना TheFramework.MyClassकाम नहीं करता है (संकलक जानता है कि आपका क्या मतलब है , लेकिन यह कहता है कि यह फ्रेमवर्क में ऐसा वर्ग नहीं खोज सकता है)।

मेरा अनुभव यह है कि स्विफ्ट मामूली नाम नहीं है। ऑब्जेक्टिव-सी से स्विफ्ट में मेरे एक ऐप को चालू करने में, मैंने एक एम्बेडेड फ्रेमवर्क बनाया क्योंकि यह करना इतना आसान और अच्छा था। हालाँकि, फ्रेमवर्क को आयात करना, फ्रेमवर्क के सभी स्विफ्ट सामानों को आयात करता है - इसलिए प्रेस्टो, एक बार फिर सिर्फ एक नाम स्थान है और यह वैश्विक है। और कोई स्विफ्ट हेडर नहीं हैं इसलिए आप किसी भी नाम को छिपा नहीं सकते हैं।

EDIT: बीज 3 में, यह सुविधा अब ऑनलाइन होने लगी है, निम्नलिखित अर्थों में: यदि आपके मुख्य कोड में MyClass है और आपके ढांचे में MyFramework में MyClass शामिल है, तो पूर्ववर्ती डिफ़ॉल्ट रूप से उत्तरार्द्ध को पूरा करता है, लेकिन आप फ्रेमवर्क में एक तक पहुँच सकते हैं। सिंटैक्स का उपयोग करके MyFramework.MyClass। इस प्रकार हम वास्तव में एक अलग नामस्थान की अशिष्टता है!

संपादित 2: बीज 4 में, अब हमारे पास पहुंच नियंत्रण है! इसके अलावा, मेरे एक ऐप में मेरे पास एक एम्बेडेड फ्रेमवर्क और पर्याप्त रूप से पर्याप्त है, सब कुछ डिफ़ॉल्ट रूप से छिपा हुआ था और मुझे सार्वजनिक एपीआई के सभी बिट्स को स्पष्ट रूप से उजागर करना था। यह एक बड़ा सुधार है।


4
इस उत्तर के लिए धन्यवाद। यह न केवल फ्रेमवर्क के साथ, बल्कि स्टैंडर्ड लाइब्रेरी के साथ भी काम करता है। उदाहरण के लिए, आप "ओवरराइट" कर सकते हैं। फिर "एरे" अपने स्वयं के कस्टम एरे वर्ग को संदर्भित करता है, और स्टैंडर्ड लाइब्रेरी का एरे "स्विफ्ट.एयर्रे" के रूप में उपलब्ध है।
जॉर्ज

3
@ जॉर्ज और इसी तरह NSArray के लिए; यदि आप इसे ओवरशेड करते हैं, तो आप अभी भी इसे देख सकते हैं Foundation.NSArray
मैट

1
तो बिना शर्त के नामस्थानों पर विचार के इतिहास के माध्यम से छाँटने के बिना: अब यह जवाब कहाँ है?
दान रोसेनस्टार्क

1
@ यर संपादन में कहा गया है। यदि कोई अस्पष्टता है, तो मॉड्यूल नाम एक वैकल्पिक नाम स्थान है, और अब गोपनीयता है इसलिए मॉड्यूल नाम छिपे हुए हैं जब तक कि उजागर नहीं किया जाता है और एक नाम एक फ़ाइल तक सीमित हो सकता है।
मैट

2
यह मुझे लंबे समय से परेशान कर रहा है, ऐसा प्रतीत होता है कि कोई भी स्विफ्ट परियोजनाएं जो कि एप्पल दावा कर रही है, उसके कारण एक उपसर्ग का उपयोग नहीं करना चाहिए, हालांकि इस समय एक उपसर्ग अभी भी आवश्यक है, यहां तक ​​कि एक्सेस संशोधक के साथ भी। जब तक आप Apple के ढांचे में पैकेज या निजी वर्गों के साथ संघर्ष नहीं करेंगे, कुछ भी सार्वजनिक घोषित किया जाता है, उदाहरण के लिए, स्ट्रिंग, यदि आप फिर से या किसी भी नए वर्ग की घोषणा करते हैं, तो यह आपका उपयोग करना समाप्त कर देगा, जब तक कि आप आदत में नहीं हैं अपने नाम स्थान के साथ सभी वर्गों का जिक्र .... अच्छा इमो नहीं।
ऑस्कर गोमेज़

19

इसके साथ कुछ प्रयोग करते हुए मैंने रूट "पैकेज" का विस्तार करके अपनी फाइलों में इन "नामांकित" कक्षाओं का निर्माण किया। यकीन नहीं होता कि क्या यह सर्वोत्तम प्रथाओं के खिलाफ है या यदि इसका कोई निहितार्थ है तो मैं इसके बारे में (?)

AppDelegate.swift

var n1 = PackageOne.Class(name: "Package 1 class")
var n2 = PackageTwo.Class(name: "Package 2 class")

println("Name 1: \(n1.name)")
println("Name 2: \(n2.name)")

PackageOne.swift

import Foundation

struct PackageOne {
}

PackageTwo.swift

import Foundation

struct PackageTwo {
}

PackageOneClass.swift

extension PackageOne {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

PackageTwoClass.swift

extension PackageTwo {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

संपादित करें:

बस पता चला है कि अलग-अलग फ़ाइलों का उपयोग करते हुए उपरोक्त कोड में "सबपैकेज" बनाने का काम नहीं होगा। शायद कोई संकेत दे सकता है कि ऐसा क्यों होगा?

उपरोक्त फ़ाइलों को जोड़ना:

PackageOneSubPackage.swift

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

PackageOneSubPackageClass.swift

extension PackageOne.SubPackage {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

संकलक त्रुटि को फेंकना: 'सबपैकेज' 'पैकेजऑन' का सदस्य प्रकार नहीं है

अगर मैं PackageOneSubPackageClass.swift से PackageOneSubPackage.swift कोड काम करता हूं तो कोड को स्थानांतरित करता हूं। किसी को?

2 संपादित करें:

इस के साथ अभी भी चारों ओर फिडिंग और पता चला (Xcode 6.1 बीटा 2 में) कि एक फ़ाइल में संकुल को परिभाषित करके उन्हें अलग-अलग फ़ाइलों में बढ़ाया जा सकता है:

public struct Package {
  public struct SubPackage {
    public struct SubPackageOne {
    }
    public struct SubPackageTwo {
    }
  }
}

यहाँ एक फाइल में मेरी फाइलें हैं: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8


दिलचस्प है, आपका परीक्षण कैसा था?
user2727195

2
निश्चित नहीं है कि आपको "परीक्षण" से क्या मतलब है, लेकिन मैं आगे बढ़ गया और उपरोक्त तकनीक का उपयोग करके अपने ऐप का निर्माण करना शुरू कर दिया और ऐसा लगता है कि अब तक केविएट के साथ मैंने अपने प्रवेश के ऊपर जोड़ा। Im ऐसा ज्यादातर इसलिए कर रहा था क्योंकि Im मेरे कोड को अन्य भाषाओं में इस तरह से व्यवस्थित करता था और आभारी रहूंगा यदि कोई भी अधिक ज्ञान वाला व्यक्ति मुझे इसका बुरा विचार बता सकता है जब तक कि मैं बहुत दूर न चला जाऊं! :)
bWlrYWphdWhvbmVu

1
चलते रहो ... यही हम चाहते हैं ... दो अलग-अलग पैकेजों में एक ही नाम वर्ग रखने में सक्षम होने के लिए मौजूद है और तदनुसार संदर्भित (अधिक महत्वपूर्ण रूप से अलग-अलग फाइलें) और अगर यह काम नहीं करता है, तो पूरे नाम स्थान का विचार एक फ्लॉप विचार है ...
user2727195

हैकनामों को हैक करने के तरीके के रूप में "संरचना" का उपयोग करते हुए कोई दुष्प्रभाव?
एलेक्स नोल्स्को

ऐसा नहीं है कि मुझे इस तरह के प्रदर्शन के संबंध में सामना करना पड़ा है। Xcode (6.1 GM) कुछ दुर्लभ मामलों में होता है जो प्रकारों की शिकायत नहीं करते हैं, लेकिन मेरा मानना ​​है कि यह मामला हो सकता है जब कोड को भी इस तरह से संरचित न किया जाए। मैंने हाल ही में अपने टेस्ट-टारगेट में सभी फाइलों को जोड़कर एक समस्या को हल किया है, जिसका कोई मतलब नहीं है, लेकिन इससे समस्या हल हो गई है। :)
bWlrYWphdWhvbmVu

12

मेरा मानना ​​है कि यह प्रयोग करके हासिल किया गया है:

struct Foo
{
    class Bar
    {
    }
}

तब इसका उपयोग करके पहुँचा जा सकता है:

var dds = Foo.Bar();

1
मैं अभी भी उस तरह से खुश नहीं हूं जिस तरह से नामस्थान किए गए हैं ... क्या होगा अगर मैंने दस अलग-अलग कक्षाएं एक नामस्थान में रखी हैं, और उसके शीर्ष पर मैं अपनी व्यक्तिगत फ़ाइलों में कक्षाएं रखना पसंद करता हूं, एक को ब्लोट नहीं करना चाहता। फ़ाइल / सभी वर्गों के साथ संरचना, किसी भी सुझाव केविन।
user2727195

2
मुझे आश्चर्य है कि उन्होंने पैकेजों को शामिल करने के लिए क्यों नहीं सोचा, यही हमें नामस्थानों की आवश्यकता है, मेरा मतलब है कि जावा, सी #, एक्शनस्क्रिप्ट जैसी अन्य उच्च स्तरीय भाषाओं को देखें, उन सभी में पैकेज हैं, इस संदर्भ में नामस्थान NS का उपयोग करने से अलग नहीं है। या आपकी परियोजना कक्षाओं के लिए अन्य उपसर्ग
user2727195

1
कैंपस सोच में मदद करता है कि क्या नेमस्पेस को हैक करने के तरीके के रूप में स्ट्रक्चर्स का उपयोग करने से अज्ञात समस्याएं हो सकती हैं।
एलेक्स नोलस्को

1
यह इसके लिए अच्छा समाधान है। मैंने इस दृष्टिकोण का उपयोग करने की कोशिश की, लेकिन तुरंत बंद करना पड़ा। जब मैंने अपने दृश्य संबंधित कक्षाओं को नामांकित करने का प्रयास किया (एक CustomTableViewCell कहता है), तो इंटरफ़ेस बिल्डर में स्वत: पूर्ण सुझाव नहीं दिया गया था। अगर मैं इस दृष्टिकोण का उपयोग करता था तो मुझे मैन्युअल रूप से वर्ग नाम को कॉपी और पेस्ट करना होगा।
अरग

1
आमतौर पर आप enumए का उपयोग करते हैं , ए का नहीं struct, इसलिए आप तत्काल नहीं कर सकते Foo
केविन

7

स्विफ्ट अजगर की तरह मॉड्यूल का उपयोग करता है ( यहाँ और यहाँ देखें ) और जैसा कि @ केविन सिल्वेस्ट्रे ने सुझाव दिया है कि आप नेस्टेड प्रकारों को नेमस्पेस के रूप में भी उपयोग कर सकते हैं ।

और डब्ल्यूडीडीसी में @ डैनियल ए व्हाइट से जवाब का विस्तार करने के लिए वे स्विफ्ट में मॉड्यूल के बारे में बात कर रहे थे।

इसके अलावा यहां समझाया गया है:

इंफ़र्ड किए गए प्रकार कोड क्लीनर और गलतियों की कम संभावना रखते हैं, जबकि मॉड्यूल हेडर को खत्म करते हैं और नाम स्थान प्रदान करते हैं।


2
मैं आपके दूसरे लिंक 6.4 पैकेज (पायथन) पर वर्णित निर्माण जैसे पैकेज की तलाश कर रहा हूं, नेस्टेड प्रकार के रूप में नामस्थान बहुत दूर नहीं ले जा सकते हैं, क्या होगा यदि मेरे पास 10 अलग-अलग कक्षाएं हैं और एक नेमस्पेस में अलग-अलग फाइलों में या मान लें कि पैकेज ???
user2727195

7
  • जब आप मौजूदा ढांचे में कक्षा के समान नाम के साथ वर्ग को परिभाषित करने की आवश्यकता हो तो नाम स्थान उपयोगी होते हैं ।

  • मान लीजिए कि आपके ऐप का MyAppनाम है, और आपको अपना रिवाज घोषित करने की आवश्यकता है UICollectionViewController

आपको इस तरह उपसर्ग और उपवर्ग की आवश्यकता नहीं है :

class MAUICollectionViewController: UICollectionViewController {}

इसको ऐसे करो:

class UICollectionViewController {} //no error "invalid redeclaration o..."

क्यों? । क्योंकि आपने जो घोषित किया है वह वर्तमान मॉड्यूल में घोषित किया गया है , जो कि आपका वर्तमान लक्ष्य है । और UICollectionViewControllerसे UIKitमें घोषित किया जाता है UIKitमॉड्यूल।

वर्तमान मॉड्यूल के भीतर इसका उपयोग कैसे करें?

var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

उन्हें दूसरे मॉड्यूल से कैसे अलग किया जाए?

var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

3

आप सही के प्रति अपने सभी कोड को इंडेंट करने के बिना नेमस्पेसिंग के लिए extensionउल्लेखित structदृष्टिकोण का उपयोग करने के लिए उपयोग कर सकते हैं । मैं इसके साथ थोड़ा सा जुड़ गया हूं और मुझे यकीन नहीं है कि मैं बनाने Controllersऔर Viewsनीचे दिए गए उदाहरणों की तरह नामस्थान पर जाऊंगा , लेकिन यह बताता है कि यह कितनी दूर जा सकता है:

Profiles.swift :

// Define the namespaces
struct Profiles {
  struct Views {}
  struct ViewControllers {}
}

प्रोफ़ाइल / ViewControllers / Edit.swift

// Define your new class within its namespace
extension Profiles.ViewControllers {
  class Edit: UIViewController {}
}

// Extend your new class to avoid the extra whitespace on the left
extension Profiles.ViewControllers.Edit {
  override func viewDidLoad() {
    // Do some stuff
  }
}

प्रोफ़ाइल / दृश्य / Edit.swift

extension Profiles.Views {
  class Edit: UIView {}
}

extension Profiles.Views.Edit {
  override func drawRect(rect: CGRect) {
    // Do some stuff
  }
}

मैंने इसे एक ऐप में उपयोग नहीं किया है क्योंकि मुझे इस अलगाव के स्तर की अभी तक ज़रूरत नहीं है लेकिन मुझे लगता है कि यह एक दिलचस्प विचार है। यह सर्वव्यापी * ViewController प्रत्यय जैसे वर्ग प्रत्यय की आवश्यकता को भी दूर करता है जो गुस्सा लंबे समय तक है।

हालाँकि, यह किसी भी चीज को छोटा नहीं करता है जब इसे संदर्भित किया जाता है जैसे कि इस तरह की विधि मापदंडों में:

class MyClass {
  func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
    // secret sauce
  }
}

2

यदि कोई व्यक्ति उत्सुक था, तो 10 जून 2014 तक, यह स्विफ्ट में एक ज्ञात बग है:

से SevenTenEleven

"ज्ञात बग, क्षमा करें! Rdar: // समस्या / 17127940 क्वालिफाइंग स्विफ्ट प्रकार उनके मॉड्यूल नाम से काम नहीं करता है।"


प्रति @ मैट पोस्ट के नीचे, यह स्विफ्ट में अभी एक ज्ञात बग है।
एडम वेंचरेल्ला

यह अब बीटा 3 (रिलीज़ जुलाई 7, 2014) में तय किया गया है
एडम वेंचरला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.