2014-10-20 11 views
5

मैं वर्तमान में एक परियोजना में कुछ स्विफ्ट कोड लिख रहा हूं जो मुख्य रूप से उद्देश्य-सी है। हमारे ओबीजेसी कोड में, हमारे पास एक हेडर है जो typedef GPUImageOutput<GPUImageInput> MyFilter; घोषित करता है। फिर हम घोषणा कर सकते हैं उदा। एक @property जो केवल GPUImageOutput सबक्लास हो सकता है जो GPUImageInput लागू करता है।`टाइपपीफ SomeClass <SomeProtocol> MyType` घोषित करने के स्विफ्ट समतुल्य क्या है?

(नोट: GPUImageOutput और GPUImageInput मेरे द्वारा परिभाषित नहीं कर रहे हैं, और वे GPUImage library का हिस्सा हैं)

हमारे स्विफ्ट कोड इस पहचान करने के लिए, भले ही शीर्ष लेख हमारे ब्रिजिंग हैडर में #imported है प्रतीत नहीं होता। मैं स्विफ्ट में घोषणा दोहराने की कोशिश की है, लेकिन इनमें से कोई भी उचित सिंटैक्स हैं:
typealias MyFilter = GPUImageOutput, GPUImageInput
typealias MyFilter = GPUImageOutput : GPUImageInput

+2

मैं यहाँ पर एक ही बात से पूछा: http://stackoverflow.com/questions/24455327/how-do-i-specify-that-a-non-generic-swift-type-should- एक ही कारण के लिए comply-to-a-प्रोटोकॉल। –

उत्तर

2

स्विफ्ट 4 में आप इस नए & संकेत के साथ (एक पैरामीटर का एक उदाहरण नीचे UIViewController को इस बात की पुष्टि प्राप्त कर सकते हैं और UITableViewDataSource:

func foo(vc: UIViewController & UITableViewDataSource) { 
    // access UIViewController property 
    let view = vc.view 
    // call UITableViewDataSource method 
    let sections = vc.numberOfSectionsInTableView?(tableView) 
} 
1

स्विफ्ट में, निम्न की तरह कुछ अपने कार्य को पूरा करना चाहिए, लेकिन यह अपने ObjC समकक्ष की तुलना में अलग है:

typealias GPUImageOutput = UIImage 
@objc protocol GPUImageInput { 
    func lotsOfInput() 
} 

class GPUImageOutputWithInput: GPUImageOutput, GPUImageInput 
{ 
    func lotsOfInput() { 
     println("lotsOfInput") 
    } 
} 

// ... 

var someGpuImage = GPUImageOutput() 
var specificGpuImage = GPUImageOutputWithInput() 

for image in [someGpuImage, specificGpuImage] { 
    if let specificImage = image as? GPUImageInput { 
     specificImage.lotsOfInput() 
    } else { 
     println("the less specific type") 
    } 
} 

अद्यतन: अब है कि मैं समझता हूँ कि जहां/तुम क्यों इन प्रकार है ...

GPUImage एक तेज उदाहरण है कि आप क्या चाहते हैं संभव के रूप में स्विफ्ट-ly के रूप में, दिखा रहा है।

here देखें:

class FilterOperation<FilterClass: GPUImageOutput where FilterClass: GPUImageInput>: FilterOperationInterface { 
... 

type constraint syntax भी कार्यों के लिए लागू किया जा सकता है, और एक where clause साथ, कि शायद के रूप में अच्छा है के रूप में आप स्विफ्ट में सीधे प्राप्त करने के लिए जा रहे हैं।

जितना अधिक मैंने यह समझने की कोशिश की कि यह कुछ सामान्य ओबीजेसी ट्रोप को कैसे बंद किया जाए, उतना ही मुझे एहसास हुआ कि यह सबसे तेज़ तरीका था। एक बार जब मैंने GPUImage में उदाहरण देखा, तो मुझे विश्वास था कि यह कम से कम आपका उत्तर था। :-)

अद्यतन 2: तो, विशिष्ट GPUImage उदाहरण मैं से जुड़ा हुआ अलावा ऊपर है कि स्विफ्ट, का उपयोग करता है और अधिक से अधिक मैं इस बारे में सोचते हैं, या तो सेटर समारोह की रक्षा के लिए एक where खंड का उपयोग कर, या एक गणनीय संपत्ति का उपयोग कर set कार्यक्षमता को फ़िल्टर करने के लिए एकमात्र तरीका लगता है।

import Foundation 

@objc protocol SpecialProtocol { 
    func special() 
} 

class MyClass {} 

class MyClassPlus: MyClass, SpecialProtocol { 
    func special() { 
     println("I'm special") 
    } 
} 

class MyContainer { 
    private var i: MyClass? 

    var test: MyClass? { 
     get { 
      return self.i 
     } 
     set (newValue) { 
      if newValue is SpecialProtocol { 
       self.i = newValue 
      } 
     } 
    } 
} 

var container = MyContainer() 

println("should be nil: \(container.test)") 

container.test = MyClass() 
println("should still be nil: \(container.test)") 

container.test = MyClassPlus() 
println("should be set: \(container.test)") 

(container.test as? MyClassPlus)?.special() 

आउटपुट:

मैं इस रणनीति के साथ आया था

should be nil: nil 
should still be nil: nil 
should be set: Optional(main.MyClassPlus) 
I'm special 

(वैकल्पिक रूप से, आप भी precondition(newValue is SpecialProtocol, "newValue did not conform to SpecialProtocol")is जांच के स्थान पर इस्तेमाल कर सकते हैं, लेकिन यह एक assert() की तरह कार्य करेगा कर सकते हैं यदि मामला पूरा नहीं हुआ है तो ऐप को क्रैश करें। आपकी ज़रूरतों पर निर्भर करता है।)

@ रिंटारो का जवाब एक अच्छा है, और यह एक अच्छा उदाहरण है where एक गार्ड के रूप में खंड (दोनों अच्छे कार्यात्मक-ly, और स्विफ्ट-लाइ)। हालांकि, जब कंप्यूटेबल गुण मौजूद हैं, तो मुझे setFoo() फ़ंक्शन लिखने से नफरत है। फिर फिर, एक कम्प्यूटेबल प्रॉपर्टी का उपयोग करने के लिए कोड गंध भी होती है, क्योंकि हम set 'एर में सामान्य प्रकार-बाधा लागू करने में सक्षम नहीं लगते हैं, और इन्हें प्रोटोकॉल अनुरूपता परीक्षण ऑनलाइन करना है।

+0

क्षमा करें, बी 'GPUImageOutput' और' GPUImageInput' '[पूर्व-मौजूद] हैं (https://github.com/BradLarson/GPUImage), इसलिए मैं उन्हें किसी भी पुराने तरीके से फिर से घोषित नहीं कर सकता। स्पष्टीकरण के लिए मेरे प्रश्न को अपडेट करेंगे! –

+0

यह सिर्फ एक उदाहरण था, क्योंकि मुझे नहीं पता था कि आपकी बेस क्लास क्या थी! कुंजी @objc प्रोटोकॉल है, जो आपको अनुरूपता का पता लगाने की अनुमति देता है, सब कुछ है। – greymouser

+0

... और प्रश्न के लिए +1 भी - यह स्विफ्ट बनाम ओबीजेसी मतभेदों का एक बहुत ही दिलचस्प मामला है। – greymouser

4

आप इस तरह के टाइपिया घोषित नहीं कर सकते हैं।

class MyClass { 
    private var filter:GPUImageOutput 

    init<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) { 
     self.filter = filter 
    } 

    func setFilter<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) { 
     self.filter = filter 
    } 

    func someMethod() { 
     let output = self.filter 
     let input = self.filter as GPUImageInput 
     output.someOutputMethod() 
     input.someInputMethod() 
    } 
} 
+0

अच्छा! हाँ, यहां एक डुप्लिकेट प्रश्न का एक समान उत्तर दिया गया है: http://stackoverflow.com/a/24455591/418982 –

-3

आप typealias कीवर्ड का उपयोग कर सकते हैं:

सबसे अच्छा हम कर सकते हैं कुछ इस तरह है। यहां बताया गया है कि यह कैसे करें:

typealias MyNewType = MyExistingType 

इससे कोई फर्क नहीं पड़ता कि MyExistingType प्रोटोकॉल या फ़ंक्शन या enum है या नहीं। यह सब कुछ प्रकार की जरूरत है। और सबसे अच्छा हिस्सा यह है कि आप उस पर अभिगम नियंत्रण लागू कर सकते हैं। आप कह सकते हैं

private typealias MyNewType = MyExistingType 

MyNewType बनाता है कि संदर्भ में परिभाषित किया गया है ही उपलब्ध है।

+0

यह प्रश्न विशेष रूप से पूछता है कि प्रोटोकॉल को लागू करने वाले वर्ग की किसी ऑब्जेक्ट के लिए टाइपलाइज़ कैसे घोषित किया जाए, केवल एक या अन्य। –

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