2017-01-13 14 views
5

मैं क्यों जहां एक सामान्य विधि के खंड नजरअंदाज कर दिया हैगलत सामान्य अधिभार समारोह

मैं स्विफ्ट 3 में एक साधारण उपयोग के मामले (यदि आप एक खेल का मैदान है, तो आप में कोड कॉपी कर सकते हैं बनाया है समझने की कोशिश कर रहा हूँ बुलाया इसके साथ झुकाव करना चाहते हैं):

//MARK: - Classes 

protocol HasChildren { 
    var children:[Human] {get} 
} 

class Human {} 

class SeniorHuman : Human, HasChildren { 
    var children: [Human] { 
     return [AdultHuman(), AdultHuman()] 
    } 
} 

class AdultHuman : Human, HasChildren { 
    var children: [Human] { 
     return [YoungHuman(), YoungHuman(), YoungHuman()] 
    } 
} 

class YoungHuman : Human {} 

//MARK: - Generic Methods 

/// This method should only be called for YoungHuman 
func sayHelloToFamily<T: Human>(of human:T) { 
    print("Hello \(human). You have no children. But do you conform to protocol? \(human is HasChildren)") 
} 

/// This method should be called for SeniorHuman and AdultHuman, but not for YoungHuman... 
func sayHelloToFamily<T: Human>(of human:T) where T: HasChildren { 
    print("Hello \(human). You have \(human.children.count) children, good for you!") 
} 

ठीक है, तो अब कुछ परीक्षण चलाएं। अगर हमने:

let senior = SeniorHuman() 
let adult = AdultHuman() 

print("Test #1") 
sayHelloToFamily(of: senior) 

print("Test #2") 
sayHelloToFamily(of: adult) 

if let seniorFirstChildren = senior.children.first { 
    print("Test #3") 
    sayHelloToFamily(of: seniorFirstChildren) 

    print("Test #4") 
    sayHelloToFamily(of: seniorFirstChildren as! AdultHuman) 
} 

उत्पादन होता है:

Test #1 
Hello SeniorHuman. You have 2 children, good for you! 

Test #2 
Hello AdultHuman. You have 3 children, good for you! 

Test #3 
Hello AdultHuman. You have no children. But do you conform to protocol? true 
//Well, why are you not calling the other method then? 

Test #4 
Hello AdultHuman. You have 3 children, good for you! 
//Oh... it's working here... It seems that I just can't use supertyping 

खैर ... जाहिरा तौर पर, where प्रोटोकॉल खंड काम करने के लिए, हम एक मजबूत प्रकार है कि में प्रोटोकॉल के अनुरूप है पारित करने के लिए की जरूरत है अपने परिभाषा।

बस सुपरर्टिंग का उपयोग करना पर्याप्त नहीं है, भले ही यह परीक्षण # 3 में स्पष्ट है कि दिया गया उदाहरण वास्तव में HasChildren प्रोटोकॉल के अनुरूप है।

तो, मैं यहां क्या खो रहा हूं, क्या यह संभव नहीं है? क्या आपके पास कुछ लिंक हैं जो हो रहा है, या where क्लॉज, या सबटाइपिंग और सामान्य रूप से इसके व्यवहार के बारे में अधिक जानकारी दे रहे हैं?

मैं कुछ उपयोगी संसाधनों पढ़ा है, लेकिन कोई भी कारण है कि यह काम नहीं कर रहा बारे में एक विस्तृत विवरण के लिए लगता है:

उत्तर

3

के प्रकार कॉल करने के लिए विधि संकलन समय के दौरान चुना जाता है। कंपाइलर आपके प्रकार के बारे में क्या जानता है?

if let seniorFirstChildren = senior.children.first { 

seniorFirstChildrenHuman है कैसे children की घोषणा की जाती है, क्योंकि है कि। हमारे पास कोई जानकारी नहीं है कि child वयस्क या वरिष्ठ है।

हालांकि, इस पर विचार करें:

if let seniorFirstChildren = senior.children.first as? AdultHuman { 

अब संकलक जानता है seniorFirstChildrenAdultHuman है और यह विधि आप उम्मीद कर कॉल करेंगे।

आप स्थिर प्रकार (संकलन के दौरान जाना जाता है प्रकार) और गतिशील प्रकार (कार्यावधि में जाना जाता है प्रकार) के बीच अंतर करने की है।

+0

अच्छा, यह बहुत स्पष्ट है जब आप इसे इस तरह कहते हैं। विश्वास नहीं कर सकता कि मुझे याद आया ... मुझे लगता है कि रिकर्सिव जेनेरिक फ़ंक्शंस का मेरा विचार ठीक से काम नहीं करेगा, अगर हम उन्हें गतिशील नहीं बना सकते हैं। –

3

the Language Guide - Type Casting से:

जाँच प्रकार

एक उदाहरण एक निश्चित उपवर्ग प्रकार का है कि क्या जांच करने के लिए प्रकार की जांच ऑपरेटर (is) का प्रयोग करें।टाइप चेक ऑपरेटर true देता है यदि उदाहरण उस सबक्लास प्रकार और false का है, तो यह नहीं है।

प्रकार की जांच ऑपरेटर isक्रम में हल हो गई है, AdultHuman के अपने को हमेशा पहली बार children सदस्य का उपयोग कर कॉल का अधिभार संकल्प sayHelloToFamily जबकि (seniorFirstChildren से आबद्ध) तर्क के रूप में संकलन समय पर हल हो गई है (जिस स्थिति में इसे Human के रूप में टाइप किया गया है, जो HasChildren के अनुरूप नहीं है)। यदि आप स्पष्ट रूप से संकलक को बताते हैं कि seniorFirstChildrenAdultHuman उदाहरण है (असुरक्षित as! AdultHuman का उपयोग करके), तो स्वाभाविक रूप से संकलक अधिक विशिष्ट अधिभार चुनने के लिए इस जानकारी का उपयोग करेगा।

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