2015-03-14 7 views
5

मैं एक प्रोटोकॉल है जो प्रकार है कि यह के अनुरूप मजबूर करता है कि एक ही प्रोटोकॉल का मान प्रदान करने के लिए, लेकिन एक विशिष्ट जुड़े प्रकार के साथ में एक समारोह की घोषणा करने के कोशिश कर रहा हूँ:एसोसिएटेड प्रकार और प्रोटोकॉल पर जेनरिक

protocol Protocol { 
    typealias ValueType 

    var value : ValueType? {get} 

    func getProtocolString<A where A : Protocol, A.ValueType == String>() -> A 
} 

यह संकलित करता है। यह जब मुझे लगता है कि मैं त्रुटियों मिल एक वर्ग है कि यह के अनुरूप बनाने की कोशिश है:

class AClass<T> : Protocol { 
    var value : T?  

    func getProtocolString<A where A : Protocol, A.ValueType == String>() -> A { 
     return AClass<String>() 
    } 
} 

त्रुटि 'Aclass' है 'ए' के ​​लिए परिवर्तनीय नहीं हैं।

क्या मुझे कुछ याद आ रही है? क्या यह भी संभव है?

धन्यवाद

+0

आप _generic_ प्रकार 'ValueType' वाले प्रोटोकॉल की घोषणा करते हैं। फिर, प्रोटोकॉल के अनुरूप होने के लिए, किसी के पास 'ValueType == स्ट्रिंग' होना चाहिए। इस प्रकार 'ValueType' का उद्देश्य _generic_ होना नहीं है। ध्यान दें कि 'स्ट्रिंग' प्रोटोकॉल नहीं है, बल्कि एक ठोस प्रकार है। –

उत्तर

2

समस्या प्रोटोकॉल के साथ प्रोटोकॉल द्वारा बाधित एक सामान्य प्लेसहोल्डर को भ्रमित करने के साथ निहित है। यहां एक सरल उदाहरण है, अपने कोड के समान, इसे साफ़ करने और इसे साफ़ करने के लिए:

// first, define a protocol and two structs that conform to it 
protocol P { } 
struct S1: P { } 
struct S2: P { } 

// now, a function that returns an object in the form 
// of a reference to protocol P 
func f() -> P { 
    // S1 conforms to P so that’s fine 
    return S1() 
} 
// ok all well and good, this works fine: 
let obj = f() 

// now, to do something similar to your example code, 
// declare a generic function that returns a generic 
// placeholder that is _constrained_ by P 
// This will NOT compile: 
func g<T: P>() -> T { return S1() } 

यह संकलित क्यों नहीं करता है?

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

नीचे दिए गए उदाहरण के साथ तो, TS1 द्वारा प्रतिस्थापित किया जाना चाहिए:

let obj1: S1 = g() 
// because T needs to be S1, the generic function g above is 
// rewritten by the compiler like this: 
func g() -> S1 { return S1() } 

यह ठीक लग रहा है। सिवाय, अगर हम TS2 के लिए चाहते थे तो क्या होगा? S2P के अनुरूप है इसलिए T के लिए एक पूरी तरह से वैध मूल्य है। लेकिन यह कैसे काम कर सकता है:

// require our result to be of type S2 
let obj2: S2 = g() 
// so T gets replaced with S2… but now we see the problem. 
// you can’t return S1 from a function that has a return type of S2. 
// this would result in a compilation error that S2 is not 
// convertible to S1 
func g() -> S2 { return S1() } 

यहां आपको प्राप्त होने वाले त्रुटि संदेश की उत्पत्ति है। आपका प्लेसहोल्डर A किसी भी प्रकार कि Protocol के अनुरूप है के लिए में खड़े हो सकते हैं, लेकिन आप एक विशिष्ट प्रकार (AClass) है कि प्रोटोकॉल के अनुरूप वापस जाने के लिए कोशिश कर रहे हैं। तो यह आपको ऐसा करने नहीं देगा।

+0

बिल्कुल सही जवाब, वास्तव में अच्छी तरह से समझाया। मैं इस तथ्य को याद कर रहा था कि संकलन जेनिक्स संकलन समय पर काम करता है। धन्यवाद। – fbernardo

0

ऐसा लगता है कि आप थोड़ा गलतफहमी जेनेरिक हैं। जेनेरिक फ़ंक्शंस इन कॉल कॉल साइटों पर तत्काल होते हैं, न कि प्रत्येक कार्य स्वयं शरीर पर। इसलिए, आपके द्वारा लिखे गए प्रकार की बाधाएं कह रही हैं कि यह फ़ंक्शन एक मान देता है, जिसमें से एक प्रकार Protocol के सभी उपप्रकारों में से कोई भी हो सकता है। नतीजतन, Protocol के सभी उपप्रकारों के लिए, केवल AClass<String> के लिए फ़ंक्शन परिभाषा A के बारे में स्थिर रूप से सही होनी चाहिए, जो केवल Protocol का एक ही प्रकार है।

किसी भी मामले में, मुझे लगता है कि कम से कम वर्तमान स्विफ्ट में आप जो चाहते हैं उसे प्राप्त करने का कोई सीधा तरीका नहीं है।

0

यह खेल के मैदान में काम करना प्रतीत होता है ... क्या यह आपके द्वारा किए जाने वाले कार्यों के लिए काम करता है?

protocol StringProtocol 
{ 
    typealias ValueType 

    var value : ValueType? { get } 

    func getProtocolString<A where A: StringProtocol, A.ValueType == String>() -> A 
} 

class StringClass : StringProtocol 
{ 
    typealias ValueType = String 

    var value : ValueType? 

    init() { } 

    func getProtocolString<A where A: StringProtocol, A.ValueType == String>() -> A 
    { 
     return StringClass() as A 
    } 
} 

मैं अभी भी इस कार्यान्वयन के साथ पूर्ण आवश्यकताओं का पालन करने की कोशिश कर रहा हूं, इसका पालन नहीं कर रहा हूं।

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