स्विफ्ट (UI) में `some` कीवर्ड क्या है?


259

नए SwiftUI ट्यूटोरियल में निम्नलिखित कोड हैं:

struct ContentView: View {
    var body: some View {
        Text("Hello World")
    }
}

दूसरी पंक्ति में शब्द some, और उनकी साइट पर हाइलाइट किया गया है जैसे कि यह एक कीवर्ड था।

स्विफ्ट 5.1 someएक कीवर्ड के रूप में दिखाई नहीं देता है , और मैं नहीं देखता कि शब्द और क्या someकर सकता है, क्योंकि यह वहां जाता है जहां टाइप आमतौर पर जाता है। क्या स्विफ्ट का कोई नया, अघोषित संस्करण है? क्या यह एक प्रकार्य है जिसका उपयोग एक प्रकार से किया जा रहा है, जिसके बारे में मुझे नहीं पता था?

कीवर्ड क्या करता someहै?


जो लोग इस विषय से चक्कर खा रहे थे, उनके लिए यहां वदीम बुलविन के लिए एक बहुत ही डिक्रिप्टिंग और कदम से कदम आलेख धन्यवाद। vadimbulavin.com/…
ल्यूक-ओलिवियर

जवाबों:


333

some Viewहै एक अपारदर्शी परिणाम प्रकार के रूप में द्वारा शुरू एसई 0244 और Xcode 11. आप के साथ स्विफ्ट 5.1 में उपलब्ध है एक "रिवर्स" जेनेरिक प्लेसहॉल्डर होने के रूप में इस के बारे में सोच सकते हैं।

एक सामान्य जेनेरिक प्लेसहोल्डर के विपरीत जो कॉलर द्वारा संतुष्ट है:

protocol P {}
struct S1 : P {}
struct S2 : P {}

func foo<T : P>(_ x: T) {}
foo(S1()) // Caller chooses T == S1.
foo(S2()) // Caller chooses T == S2.

एक अपारदर्शी परिणाम प्रकार एक अंतर्निहित जेनेरिक प्लेसहोल्डर है जो कार्यान्वयन से संतुष्ट है , इसलिए आप इस बारे में सोच सकते हैं:

func bar() -> some P {
  return S1() // Implementation chooses S1 for the opaque result.
}

जैसा दिख रहा है:

func bar() -> <Output : P> Output {
  return S1() // Implementation chooses Output == S1.
}

वास्तव में, इस सुविधा के साथ अंतिम लक्ष्य यह है कि इस तरह के अधिक स्पष्ट रूप में रिवर्स जेनेरिक की अनुमति दी जाए, जो आपको बाधाओं को भी जोड़ने देगा, जैसे -> <T : Collection> T where T.Element == Intअधिक जानकारी के लिए इस पोस्ट को देखें

इस से दूर करने के लिए मुख्य बात यह है कि लौटने वाला एक फ़ंक्शन वह some Pहै जो एक विशिष्ट एकल कंक्रीट प्रकार का मूल्य देता है जो इसके अनुरूप होता है P। फ़ंक्शन के भीतर विभिन्न अनुरूप प्रकारों को वापस करने का प्रयास करने से एक संकलक त्रुटि उत्पन्न होती है:

// error: Function declares an opaque return type, but the return
// statements in its body do not have matching underlying types.
func bar(_ x: Int) -> some P {
  if x > 10 {
    return S1()
  } else {
    return S2()
  }
}

जैसा कि निहित जेनेरिक प्लेसहोल्डर कई प्रकारों से संतुष्ट नहीं हो सकता है।

यह एक फ़ंक्शन रिटर्निंग के विपरीत है P, जिसका उपयोग दोनों का प्रतिनिधित्व करने के लिए किया जा सकता है S1और S2क्योंकि यह एक मनमाना Pअनुरूपता मूल्य का प्रतिनिधित्व करता है :

func baz(_ x: Int) -> P {
  if x > 10 {
    return S1()
  } else {
    return S2()
  }
}

ठीक है, इसलिए अपारदर्शी परिणाम प्रकारों के -> some Pप्रोटोकॉल रिटर्न प्रकारों के क्या लाभ हैं-> P ?


1. पीएटी के साथ अपारदर्शी परिणाम प्रकार का उपयोग किया जा सकता है

प्रोटोकॉल की एक प्रमुख वर्तमान सीमा यह है कि PATs (संबद्ध प्रकार के प्रोटोकॉल) को वास्तविक प्रकारों के रूप में उपयोग नहीं किया जा सकता है। यद्यपि यह एक प्रतिबंध है जो संभवतः भाषा के भविष्य के संस्करण में उठा लिया जाएगा, क्योंकि अपारदर्शी परिणाम प्रकार प्रभावी रूप से सिर्फ सामान्य प्लेसहोल्डर हैं, उन्हें आज PAT के साथ उपयोग किया जा सकता है।

इसका मतलब है कि आप इस तरह की चीजें कर सकते हैं:

func giveMeACollection() -> some Collection {
  return [1, 2, 3]
}

let collection = giveMeACollection()
print(collection.count) // 3

2. अपारदर्शी परिणाम प्रकारों की पहचान होती है

क्योंकि अपारदर्शी परिणाम प्रकार एक एकल कंक्रीट प्रकार को लागू करता है, इसलिए संकलक जानता है कि एक ही फ़ंक्शन के दो कॉल को एक ही प्रकार के दो मान वापस करने होंगे।

इसका मतलब है कि आप इस तरह की चीजें कर सकते हैं:

//   foo() -> <Output : Equatable> Output {
func foo() -> some Equatable { 
  return 5 // The opaque result type is inferred to be Int.
}

let x = foo()
let y = foo()
print(x == y) // Legal both x and y have the return type of foo.

यह कानूनी है क्योंकि कंपाइलर जानता है कि दोनों xऔर yएक ही ठोस प्रकार है। यह एक महत्वपूर्ण आवश्यकता है ==, जहां दोनों प्रकार के पैरामीटर Self

protocol Equatable {
  static func == (lhs: Self, rhs: Self) -> Bool
}

इसका मतलब यह है कि यह दो मूल्यों की अपेक्षा करता है जो दोनों एक ही प्रकार के ठोस अनुरूप प्रकार हैं। यहां तक ​​कि अगर Equatableएक प्रकार के रूप में उपयोग करने योग्य थे, तो आप Equatableएक दूसरे के साथ दो मनमाने ढंग से मूल्यों की तुलना करने में सक्षम नहीं होंगे , उदाहरण के लिए:

func foo(_ x: Int) -> Equatable { // Assume this is legal.
  if x > 10 {
    return 0
  } else {
    return "hello world"      
  }
}

let x = foo(20)
let y = foo(5)
print(x == y) // Illegal.

जैसा कि संकलक यह साबित नहीं कर सकता कि दो मनमाने Equatableमूल्यों में एक ही अंतर्निहित ठोस प्रकार है।

इसी तरह से, अगर हमने एक और अपारदर्शी प्रकार की वापसी समारोह पेश किया:

//   foo() -> <Output1 : Equatable> Output1 {
func foo() -> some Equatable { 
  return 5 // The opaque result type is inferred to be Int.
}

//   bar() -> <Output2 : Equatable> Output2 {
func bar() -> some Equatable { 
  return "" // The opaque result type is inferred to be String.
}

let x = foo()
let y = bar()
print(x == y) // Illegal, the return type of foo != return type of bar.

उदाहरण अवैध हो जाता है , हालांकि दोनों fooऔर barवापस some Equatable, उनके "रिवर्स" जेनेरिक प्लेसहोल्डर्स Output1और Output2विभिन्न प्रकारों से संतुष्ट हो सकते हैं।


3. अपारदर्शी परिणाम प्रकार जेनेरिक प्लेसहोल्डर्स के साथ रचना करते हैं

नियमित प्रोटोकॉल-टाइप किए गए मूल्यों के विपरीत, अपारदर्शी परिणाम प्रकार नियमित जेनेरिक प्लेसहोल्डर्स के साथ अच्छी तरह से रचना करते हैं, उदाहरण के लिए:

protocol P {
  var i: Int { get }
}
struct S : P {
  var i: Int
}

func makeP() -> some P { // Opaque result type inferred to be S.
  return S(i: .random(in: 0 ..< 10))
}

func bar<T : P>(_ x: T, _ y: T) -> T {
  return x.i < y.i ? x : y
}

let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Legal, T is inferred to be the return type of makeP.

यह अगर काम नहीं किया होता makePतो बस लौटा था P, दो के रूप में Pमान भिन्न अंतर्निहित ठोस प्रकार, उदाहरण के लिए हो सकता है:

struct T : P {
  var i: Int
}

func makeP() -> P {
  if .random() { // 50:50 chance of picking each branch.
    return S(i: 0)
  } else {
    return T(i: 1)
  }
}

let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Illegal.

कंक्रीट प्रकार पर एक अपारदर्शी परिणाम प्रकार का उपयोग क्यों करें?

इस बिंदु पर आप अपने आप को सोच रहे होंगे कि क्यों न केवल कोड लिखें:

func makeP() -> S {
  return S(i: 0)
}

ठीक है, एक अपारदर्शी परिणाम प्रकार का उपयोग आपको Sकेवल प्रदान किए गए इंटरफ़ेस को उजागर करके प्रकार को एक कार्यान्वयन विवरण बनाने की अनुमति देता हैP , जिससे आपको किसी भी कोड को तोड़ने के बिना बाद में लाइन के नीचे कंक्रीट प्रकार को बदलने का लचीलापन मिलता है जो फ़ंक्शन पर निर्भर करता है।

उदाहरण के लिए, आप प्रतिस्थापित कर सकते हैं:

func makeP() -> some P {
  return S(i: 0)
}

साथ में:

func makeP() -> some P { 
  return T(i: 1)
}

किसी भी कोड को तोड़ने के बिना जो कॉल करता है makeP()

देखें अपारदर्शी प्रकार अनुभाग भाषा गाइड की और स्विफ्ट विकास प्रस्ताव इस सुविधा पर अधिक जानकारी के लिए।


20
असंबंधित: स्विफ्ट 5.1 के रूप में, returnएकल-अभिव्यक्ति कार्यों में आवश्यक नहीं है
ielyamani

3
लेकिन क्या अंतर है: func makeP() -> some Pऔर func makeP() -> P? मैंने प्रस्ताव पढ़ा है, और उनके नमूनों के लिए भी यह अंतर नहीं देख सकता।
आर्टेम


2
स्विफ्ट टाइप हैंडलिंग एक गड़बड़ है। क्या यह विशिष्टता वास्तव में ऐसा कुछ है जिसे संकलित समय पर संभाला नहीं जा सकता है? देखें सी # संदर्भ के लिए यह सरल वाक्य रचना के माध्यम से इन सभी मामलों को संभालता है। स्विफ्ट को स्पष्ट रूप से स्पष्ट रूप से लगभग कार्गो-कल्चर सिंटैक्स की आवश्यकता होती है जो वास्तव में भाषा को बाधित करता है। क्या आप कृपया इसके लिए डिज़ाइन के तर्क को भी समझा सकते हैं? (यदि आपके पास जीथब में प्रस्ताव का एक लिंक है जो बहुत अच्छा होगा) संपादित करें: बस इसे शीर्ष पर जुड़ा हुआ देखा।
SacredGeometry

2
@Zmaster कंपाइलर दो अपारदर्शी रिटर्न प्रकारों को अलग-अलग मानेंगे भले ही कार्यान्वयन दोनों के लिए एक ही ठोस प्रकार देता है। दूसरे शब्दों में, चुने गए विशिष्ट ठोस प्रकार को कॉलर से छिपाया जाता है। (मेरा मतलब है कि मेरे उत्तर के उत्तरार्ध का विस्तार इस तरह की चीजों को थोड़ा और स्पष्ट करने के लिए किया गया है, लेकिन अभी तक इसका कोई दौर नहीं आया है)।
हामिश

52

दूसरा उत्तर नए someकीवर्ड के तकनीकी पहलू को समझाने का अच्छा काम करता है लेकिन यह उत्तर आसानी से समझाने की कोशिश करेगा कि क्यों


मान लीजिए कि मेरे पास एक प्रोटोकॉल है पशु और मैं तुलना करना चाहता हूं कि क्या दो जानवर भाई बहन हैं:

protocol Animal {
    func isSibling(_ animal: Self) -> Bool
}

इस तरह से यह तुलना करने के लिए ही समझ में आता है कि यदि दो जानवर एक ही प्रकार के जानवर हैं तो भाई बहन हैं


अब मुझे केवल संदर्भ के लिए एक जानवर का एक उदाहरण बनाने दें

class Dog: Animal {
    func isSibling(_ animal: Dog) -> Bool {
        return true // doesn't really matter implementation of this
    }
}

बिना रास्ता some T

अब हम कहते हैं कि मेरे पास एक फ़ंक्शन है जो एक 'परिवार' से एक जानवर लौटाता है।

func animalFromAnimalFamily() -> Animal {
    return myDog // myDog is just some random variable of type `Dog`
}

नोट: यह फ़ंक्शन वास्तव में संकलन नहीं करेगा। ऐसा इसलिए है क्योंकि 'कुछ' सुविधा को जोड़ने से पहले आप प्रोटोकॉल प्रकार को वापस नहीं कर सकते हैं यदि प्रोटोकॉल 'स्व' या जेनरिक का उपयोग करता है । लेकिन हम कहते हैं कि आप कर सकते हैं ... इस प्रकार का दिखावा myDog to अमूर्त प्रकार पशु, चलो देखते हैं क्या होता है

अब मुद्दा यह है कि क्या मैं ऐसा करने की कोशिश करता हूं:

let animal1: Animal = animalFromAnimalFamily()
let animal2: Animal = animalFromAnimalFamily()

animal1.isSibling(animal2) // error

यह एक त्रुटि फेंक देगा

क्यों? वैसे इसका कारण यह है कि जब आप animal1.isSibling(animal2)स्विफ्ट कहते हैं तो यह नहीं जानते कि जानवर कुत्ते, बिल्ली या जो भी हैं। जहां तक ​​स्विफ्ट को पता है, animal1और animal2असंबंधित पशु प्रजातियां हो सकती हैं । चूंकि हम विभिन्न प्रकार के जानवरों की तुलना नहीं कर सकते (ऊपर देखें)। यह त्रुटि करेगा

some Tयह समस्या कैसे हल करता है

आइए पिछले समारोह को फिर से लिखें:

func animalFromAnimalFamily() -> some Animal {
    return myDog
}
let animal1 = animalFromAnimalFamily()
let animal2 = animalFromAnimalFamily()

animal1.isSibling(animal2)

animal1और animal2कर रहे हैं नहीं Animal , लेकिन वे कक्षा कि औजार पशु हैं

जब आप कॉल करते हैं तो यह आपको क्या करने देता है animal1.isSibling(animal2), स्विफ्ट जानता है animal1और animal2उसी प्रकार का है।

तो जिस तरह से मैं इसके बारे में सोचना पसंद करता हूं:

some Tकी सुविधा देता है स्विफ्ट क्या के कार्यान्वयन पता Tकिया जा रहा है लेकिन वर्ग के उपयोगकर्ता नहीं करता है।

(सेल्फ-प्रमोशन डिस्क्लेमर) मैंने एक ब्लॉग पोस्ट लिखी है जो इस नई सुविधा पर थोड़ी और गहराई (उदाहरण के रूप में यहाँ) पर जाती है


2
तो आपका विचार यह है कि कॉलर इस तथ्य का लाभ उठा सकता है कि फ़ंक्शन के दो कॉल उसी प्रकार वापस करते हैं, भले ही कॉलर को यह पता न हो कि यह किस प्रकार का है?
मैट

1
@ मट मूल रूप से युप। समान अवधारणा जब खेतों के साथ उपयोग की जाती है, आदि-तो कॉलर को यह गारंटी दी जाती है कि रिटर्न प्रकार हमेशा एक ही प्रकार का होगा, लेकिन वास्तव में यह नहीं बताता है कि प्रकार क्या है।
डाउनगोट

@Downgoat सही पोस्ट और जवाब के लिए बहुत बहुत धन्यवाद। जैसा कि मैंने someरिटर्न प्रकार में समझा कि फ़ंक्शन के शरीर के लिए बाधा के रूप में काम करता है। इसलिए someपूरे फ़ंक्शन बॉडी में केवल एक ठोस प्रकार को वापस करने की आवश्यकता है। उदाहरण के लिए: यदि वहाँ है return randomDogतो अन्य सभी रिटर्न के साथ ही काम करना होगा Dog। सभी लाभ इस बाधा से आते हैं: (अब हुड के तहत परिभाषित हो जाता है) animal1.isSibling(animal2)के संकलन की उपलब्धता और लाभ । क्या यह सही है? func animalFromAnimalFamily() -> some AnimalSelf
आर्टेम

5
इस लाइन मैं सभी की जरूरत थी, Animal1 और animal2 पशु नहीं हैं, लेकिन वे वर्ग हैं जो पशु को लागू करते हैं, अब सभी समझ में आता है!
शाम

29

हामिश का जवाब बहुत ही बढ़िया है और तकनीकी दृष्टिकोण से सवाल का जवाब देता है। मैं इस पर कुछ विचार जोड़ना चाहूंगा कि someApple के SwiftUI ट्यूटोरियल्स में इस विशेष स्थान पर कीवर्ड का उपयोग क्यों किया गया है और इसका पालन करना एक अच्छा अभ्यास क्यों है।

some एक आवश्यकता नहीं है!

सबसे पहले, आपको एक अपारदर्शी प्रकार के रूप में वापसी की घोषणा करने की आवश्यकता नहीं हैbody । आप हमेशा का उपयोग करने के बजाय ठोस प्रकार वापस कर सकते हैं some View

struct ContentView: View {
    var body: Text {
        Text("Hello World")
    }
}

यह भी संकलन होगा। जब आप View's इंटरफ़ेस में देखते हैं, तो आप देखेंगे कि वापसी प्रकार bodyएक संबद्ध प्रकार है:

public protocol View : _View {

    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    associatedtype Body : View

    /// Declares the content and behavior of this view.
    var body: Self.Body { get }
}

इसका मतलब है कि आपbody अपनी पसंद के किसी विशेष प्रकार के साथ संपत्ति की घोषणा करके इस प्रकार को निर्दिष्ट करते हैं। केवल आवश्यकता यह है कि इस प्रकार को Viewप्रोटोकॉल को लागू करने की आवश्यकता है।

वह या तो एक विशिष्ट प्रकार हो सकता है जो Viewउदाहरण के लिए लागू होता है

  • Text
  • Image
  • Circle
  • ...

या एक अपारदर्शी प्रकार जो लागू होता है View, अर्थात

  • some View

सामान्य दृश्य

समस्या तब उत्पन्न होती है जब हम एक स्टैक दृश्य का उपयोग करने का प्रयास करते हैं body, जैसे : VStackयाHStack

struct ContentView: View {
    var body: VStack {
        VStack {
            Text("Hello World")
            Image(systemName: "video.fill")
        }
    }
}

यह संकलन नहीं करेगा और आपको त्रुटि मिलेगी:

जेनेरिक प्रकार 'VStack' के संदर्भ में <...> में तर्क की आवश्यकता है

के ऐसा इसलिए है क्योंकि में ढेर विचारों SwiftUI हैं सामान्य प्रकार! Same (और सूची और अन्य कंटेनर दृश्य प्रकारों के लिए भी यही सच है ।)

यह बहुत मायने रखता है क्योंकि आप किसी भी प्रकार के किसी भी दृश्य में प्लग कर सकते हैं (जब तक कि यह Viewप्रोटोकॉल के अनुरूप हो )। VStackऊपर के शरीर में कंक्रीट का प्रकार वास्तव में है

VStack<TupleView<(Text, Image)>>

जब हम बाद में स्टैक में एक दृश्य जोड़ने का निर्णय लेते हैं, तो इसका ठोस प्रकार बदल जाता है। यदि हम पहले वाले के बाद एक दूसरा पाठ जोड़ते हैं, तो हम प्राप्त करते हैं

VStack<TupleView<(Text, Text, Image)>>    

यहां तक ​​कि अगर हम एक मामूली बदलाव करते हैं, तो पाठ और छवि के बीच स्पेसर जोड़ने के रूप में सूक्ष्म रूप से कुछ, स्टैक का प्रकार बदलता है:

VStack<TupleView<(Text, _ModifiedContent<Spacer, _FrameLayout>, Image)>>

मैं क्या बता सकते हैं, यह है कि कारण है कि एप्पल अपने ट्यूटोरियल में हमेशा से उपयोग करने के लिए सिफारिश की गई है some View, सबसे सामान्य अपारदर्शी प्रकार है जो सभी विचारों के रूप में संतुष्ट, bodyकी वापसी प्रकार। आप हर बार रिटर्न प्रकार को मैन्युअल रूप से बदले बिना कार्यान्वयन / अपने कस्टम दृश्य के लेआउट को बदल सकते हैं।


अनुपूरक:

यदि आप अपारदर्शी परिणाम प्रकारों के बारे में अधिक सहज ज्ञान प्राप्त करना चाहते हैं, तो मैंने हाल ही में एक लेख प्रकाशित किया है जो पढ़ने योग्य हो सकता है:

UI स्विफ्टयूआई में यह "कुछ" क्या है?


2
यह। धन्यवाद! हामिश का जवाब बहुत ही पूरा था, लेकिन आप मुझे बताती हैं कि इन उदाहरणों में इसका उपयोग क्यों किया गया है।
क्रिस मार्शल

मुझे "कुछ" के विचार से प्यार है। किसी भी विचार अगर "कुछ" का उपयोग कर संकलन समय को प्रभावित करता है?
टोफू योद्धा

@ मिशा तो जेनेरिक व्यू कैसे बना सकते हैं? एक प्रोटोकॉल के साथ, जिसमें अन्य व्यवहार के बारे में विचार हैं?
TheMouk

27

मुझे लगता है कि अब तक के सभी उत्तर गायब हैं जो कि someमुख्य रूप से एक डीएसएल (डोमेन-विशिष्ट भाषा) जैसे कि स्विफ्टयूआई या लाइब्रेरी / फ्रेमवर्क जैसे उपयोगी हैं, जिनमें उपयोगकर्ता (अन्य प्रोग्रामर) खुद से अलग होंगे।

आप शायद someअपने सामान्य ऐप कोड में कभी भी उपयोग नहीं करेंगे , शायद इंफोर्स को छोड़कर क्योंकि यह एक जेनेरिक प्रोटोकॉल को लपेट सकता है ताकि इसे एक प्रकार (केवल एक प्रकार की बाधा के रूप में) के रूप में उपयोग किया जा सके। क्या someकरता है संकलक, क्या विशेष प्रकार कुछ है का ज्ञान रखने, जबकि यह के सामने एक महाप्रकार मुखौटा डाल देना है।

इस प्रकार स्विफ्टयूआई में, जहां आप उपयोगकर्ता हैं, आपको बस यह जानना होगा कि कुछ एक है some View, जबकि पर्दे के पीछे सभी प्रकार के हंकी-पैंकी चल सकते हैं, जिनसे आप परिरक्षित हैं। यह वस्तु वास्तव में एक बहुत ही विशिष्ट प्रकार है, लेकिन आपको इसके बारे में कभी सुनने की आवश्यकता नहीं होगी कि यह क्या है। फिर भी, एक प्रोटोकॉल के विपरीत, यह एक पूर्ण प्रकार है, क्योंकि जहां भी यह प्रतीत होता है, यह कुछ विशिष्ट पूर्ण प्रकार के लिए केवल एक मुखौटा है।

SwiftUI के भविष्य के संस्करण में, जहां आप एक की उम्मीद कर रहे हैं some View, डेवलपर्स उस विशेष वस्तु के अंतर्निहित प्रकार को बदल सकते हैं। लेकिन इससे आपका कोड नहीं टूटेगा, क्योंकि आपके कोड ने पहले स्थान पर अंतर्निहित प्रकार का उल्लेख नहीं किया है।

इस प्रकार, someप्रभाव एक प्रोटोकॉल को सुपरक्लास की तरह बनाता है। यह लगभग एक वास्तविक वस्तु प्रकार है, हालांकि काफी नहीं है (उदाहरण के लिए, एक प्रोटोकॉल की विधि घोषणा वापस नहीं आ सकती है some)।

इसलिए यदि आप someकिसी भी चीज़ के लिए उपयोग करने जा रहे हैं , तो यह सबसे अधिक संभावना है यदि आप दूसरों द्वारा उपयोग के लिए एक डीएसएल या फ्रेमवर्क / लाइब्रेरी लिख रहे थे, और आप अंतर्निहित प्रकार के विवरणों को मुखौटा करना चाहते थे। इससे आपका कोड दूसरों के उपयोग के लिए सरल हो जाएगा, और आपको उनके कोड को तोड़ने के बिना कार्यान्वयन विवरण बदलने की अनुमति देगा।

हालाँकि, आप इसे अपने कोड के किसी अन्य क्षेत्र में दफन किए गए कार्यान्वयन विवरण से अपने कोड के एक क्षेत्र को परिरक्षण के तरीके के रूप में भी उपयोग कर सकते हैं।


22

someस्विफ्ट 5.1 (से कीवर्ड तेज विकास प्रस्ताव ) एक वापसी प्रकार के रूप में एक प्रोटोकॉल के साथ संयोजन के रूप में प्रयोग किया जाता है।

Xcode 11 रिलीज़ नोट इसे इस तरह प्रस्तुत करते हैं:

फ़ंक्शंस अब उनके कंक्रीट रिटर्न प्रकार को यह घोषित करके छुपा सकते हैं कि सटीक रिटर्न प्रकार को निर्दिष्ट करने के बजाय, यह किस प्रोटोकॉल के अनुरूप है:

func makeACollection() -> some Collection {
    return [1, 2, 3]
}

फ़ंक्शन को कॉल करने वाला कोड प्रोटोकॉल के इंटरफ़ेस का उपयोग कर सकता है, लेकिन अंतर्निहित प्रकार में दृश्यता नहीं है। ( एसई -0244, 40538331)

उपरोक्त उदाहरण में, आपको यह बताने की आवश्यकता नहीं है कि आप वापस लौटने वाले हैं Array। यह आपको एक सामान्य प्रकार को भी वापस करने की अनुमति देता है जो बस के अनुरूप है Collection


इस संभावित त्रुटि पर भी ध्यान दें जो आपको सामना करना पड़ सकता है:

'कुछ' रिटर्न प्रकार केवल iOS 13.0.0 या नए में उपलब्ध हैं

इसका अर्थ है कि आप someiOS 12 और उससे पहले से बचने के लिए उपलब्धता का उपयोग करने वाले हैं :

@available(iOS 13.0, *)
func makeACollection() -> some Collection {
    ...
}

1
इस केंद्रित जवाब और Xcode 11 बीटा में संकलक समस्या के लिए बहुत धन्यवाद
ब्रेनर्रे

1
आप someiOS 12 और उससे पहले से बचने के लिए उपलब्धता का उपयोग करने वाले हैं । जब तक आप करते हैं, तब तक आपको ठीक होना चाहिए। मुद्दा केवल यह है कि संकलक आपको ऐसा करने के लिए चेतावनी नहीं देता है।
मैट

2
हालांकि, जैसा कि आप बताते हैं, संक्षिप्त विवरण Apple विवरण यह सब बताता है: कार्य अब सटीक रिटर्न प्रकार को निर्दिष्ट करने के बजाय, जो भी प्रोटोकॉल के अनुरूप है, यह घोषित करके अपने कंक्रीट रिटर्न प्रकार को छिपा सकता है। और फिर फ़ंक्शन को कॉल करने वाला कोड प्रोटोकॉल इंटरफ़ेस का उपयोग कर सकता है। नीट और फिर कुछ।
फेटी

यह (कंक्रीट रिटर्न प्रकार को छिपाते हुए) कीवर्ड "कुछ" का उपयोग किए बिना पहले से ही संभव है। यह विधि हस्ताक्षर में "कुछ" जोड़ने के प्रभाव की व्याख्या नहीं करता है।
विंस ओ'सुल्लिवन

@ VinceO'Sullivan someस्विफ्ट 5.0 या स्विफ्ट 4.2 में इस दिए गए कोड नमूने में कीवर्ड को निकालना संभव नहीं है । त्रुटि होगी: " प्रोटोकॉल 'संग्रह' केवल एक सामान्य बाधा के रूप में इस्तेमाल किया जा सकता है क्योंकि इसमें स्वयं या संबंधित प्रकार की आवश्यकताएं हैं "
C'ur

2

'कुछ' का अर्थ है अपारदर्शी प्रकार। SwiftUI में, View को एक प्रोटोकॉल के रूप में घोषित किया गया है

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol View {

    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    associatedtype Body : View

    /// Declares the content and behavior of this view.
    var body: Self.Body { get }
}

जब आप अपना दृश्य संरचना के रूप में बनाते हैं, तो आप दृश्य प्रोटोकॉल के अनुरूप होते हैं और बताते हैं कि var body कुछ लौटाएगा जो View प्रोटोकॉल की पुष्टि करेगा। यह एक सामान्य प्रोटोकॉल अमूर्त की तरह है जहाँ आपको ठोस प्रकार को परिभाषित करने की आवश्यकता नहीं है।


1

मैं इसका उत्तर बहुत ही व्यावहारिक उदाहरण के साथ देने की कोशिश करूँगा (यह एक अपारदर्शी परिणाम प्रकार क्या है )

मान लें कि आपके पास संबंधित प्रकार के साथ प्रोटोकॉल है, और इसे लागू करने वाले दो संरचनाएं:

protocol ProtocolWithAssociatedType {
    associatedtype SomeType
}

struct First: ProtocolWithAssociatedType {
    typealias SomeType = Int
}

struct Second: ProtocolWithAssociatedType {
    typealias SomeType = String
}

स्विफ्ट 5.1 से पहले, ProtocolWithAssociatedType can only be used as a generic constraintत्रुटि के कारण नीचे अवैध है :

func create() -> ProtocolWithAssociatedType {
    return First()
}

लेकिन स्विफ्ट 5.1 में यह ठीक है ( someजोड़ा गया):

func create() -> some ProtocolWithAssociatedType {
    return First()
}

ऊपर व्यावहारिक उपयोग है, के लिए व्यापक रूप से SwiftUI में उपयोग किया जाता है some View

लेकिन एक महत्वपूर्ण सीमा है - लौटने के प्रकार को संकलन समय पर पता होना चाहिए, इसलिए नीचे फिर से Function declares an opaque return type, but the return statements in its body do not have matching underlying typesत्रुटि देने का काम नहीं किया जाएगा :

func create() -> some ProtocolWithAssociatedType {
    if (1...2).randomElement() == 1 {
        return First()
    } else {
        return Second()
    }
}

0

एक साधारण उपयोग मामला जो मन में झरता है वह संख्यात्मक प्रकारों के लिए सामान्य कार्य लिख रहा है।

/// Adds one to any decimal type
func addOne<Value: FloatingPoint>(_ x: Value) -> some FloatingPoint {
    x + 1
}

// Variables will be assigned 'some FloatingPoint' type
let double = addOne(Double.pi) // 4.141592653589793
let float = addOne(Float.pi) // 4.141593

// Still get all of the required attributes/functions by the FloatingPoint protocol
double.squareRoot() // 2.035090330572526
float.squareRoot() // 2.03509

// Be careful, however, not to combine 2 'some FloatingPoint' variables
double + double // OK 
//double + float // error

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.