2014-12-15 8 views
7

स्विफ्ट विरासत में उद्देश्य-सी की मेटाक्लास अवधारणा: कक्षाओं को स्वयं वस्तुओं के रूप में भी माना जाता है। एक वर्ग Foo की ऑब्जेक्ट की कक्षा Foo.self है, और यह Foo.Type प्रकार है। FooBar से विरासत प्राप्त करता है, तो Foo.self को Bar.Type प्रकार के चर के लिए भी असाइन किया जा सकता है। इसमें कम से कम दो लाभ हैं:क्या मैं स्विफ्ट में प्रोटोकॉल प्रकार में मेटाक्लास ऑब्जेक्ट डाल सकता हूं?

  • यह "स्थैतिक विधियों" को ओवरराइड करने की अनुमति देता है;
  • किसी अज्ञात वर्ग का एक प्रकार-सुरक्षित तरीके से और प्रतिबिंब का उपयोग किए बिना उदाहरण बनाना आसान है।

मैं विशेष रूप से अभी दूसरे को देख रहा हूं। बस सुनिश्चित करें कि हर कोई समझता है कि मैं क्या करने के बाद कर रहा हूँ हो सकता है, यहाँ एक उदाहरण है:

class BaseFoo { 
    var description: String { return "BaseFoo" } 
} 

class DerivedFoo: BaseFoo { 
    override var description: String { return "DerivedFoo" } 
} 

let fooTypes: [BaseFoo.Type] = [BaseFoo.self, DerivedFoo.self] // metaclass magic! 
for type in fooTypes { 
    let object: BaseFoo = type() // metaclass magic! 
    println(object) 
} 

अब, मैं AnyClass वस्तुओं (किसी भी metaclass उदाहरण की तरह किसी भी वस्तु सौंपा जा सकता है AnyClass को सौंपा जा सकता, की एक सरणी है AnyObject पर), और मैं यह जानना चाहता हूं कि कौन से किसी दिए गए प्रोटोकॉल को लागू करते हैं। प्रोटोकॉल एक प्रारंभकर्ता घोषित करेगा, और मैं उपरोक्त उदाहरण में जैसा क्लास को तुरंत चालू करता हूं। उदाहरण के लिए:

protocol Foo { 
    init(foo: String) 
} 

class Bar: Foo { 
    required init(foo: String) { println("Bar initialized with \(foo)") } 
} 

class Baz { 
    required init() { println("I'm not a Foo!") } 
} 

let types: [AnyClass] = [Bar.self, Baz.self] 

अब तक इतना अच्छा है। अब, समस्या यह निर्धारित कर रही है कि कक्षा प्रोटोकॉल लागू करती है या नहीं। चूंकि मेटाक्लास उदाहरण पॉलीमोर्फिक हैं, इसलिए मैं उन्हें कास्ट करने में सक्षम होने की उम्मीद करता हूं। हालांकि, मैं जाहिरा तौर पर कुछ याद कर रहा हूँ, क्योंकि स्विफ्ट मुझे इस बारे में नहीं दूँगी:

for type in types { 
    if let fooType = type as? Foo.Type { 
     let obj = fooType(foo: "special snowflake string") 
    } 
} 

संकलक त्रुटि मैं मिलता है:

त्रुटि: 'फू' के समान नहीं है 'AnyObject'

क्या यह निर्धारित करने का कोई तरीका है कि मेटाक्लास उदाहरण एक वर्ग को दर्शाता है जो प्रोटोकॉल लागू करता है, और क्या उस उदाहरण को प्रोटोकॉल प्रकार में डालने का कोई तरीका है?

मैंने कक्षा प्रोटोकॉल के रूप में Foo घोषित करने की कोशिश की, लेकिन यह स्पष्ट रूप से पर्याप्त नहीं है।


संपादित: मैं बस Any प्रकार के साथ की कोशिश की, और जब तक यह एक सिंटैक्स त्रुटि का कारण नहीं है, यह स्विफ्ट संकलक दुर्घटनाओं।

+0

संकलक क्रैश हुआ? [एक बग फाइल करें] (http://bugreport.apple.com)। – rickster

+0

मैंने पहले ही ऐसा किया था। – zneak

+0

यय! वास्तविक मुद्दे के लिए, मुझे यकीन नहीं है कि मेटाक्लास वर्तमान स्विफ्ट में आत्मनिर्भर हैं। – rickster

उत्तर

4

एक्सकोड 7 बीटा 2 और स्विफ्ट 2 के रूप में इसे ठीक किया गया है। अब आप लिख सकते हैं:

for type in types { 
    if let fooType = type as? Foo.Type { 
     // in Swift 2 you have to explicitly call the initializer of metatypes 
     let obj = fooType.init(foo: "special snowflake string") 
    } 
} 

या यदि आप केवल type प्रकार के रूप में चाहते हैं आप Foo.Type उपयोग कर सकते हैं for case

for case let type as Foo.Type in types { 
    let obj = type.init(foo: "special snowflake string") 
} 
संबंधित मुद्दे