সুইফট (ইউআই) এর `কিছু` কীওয়ার্ডটি কী?


258

নতুন SwiftUI টিউটোরিয়ালে নিম্নলিখিত কোড রয়েছে:

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

শব্দটি someএবং তাদের সাইটে দ্বিতীয় লাইনটি হাইলাইট করা হয়েছে যেন এটি কোনও কীওয়ার্ড।

সুইফ্ট 5.1 তে কোনও someকীওয়ার্ড হিসাবে উপস্থিত হয় না এবং শব্দটি someসেখানে কী করতে পারে তা আমি দেখতে পাই না , কারণ এটি টাইপটি সাধারণত সেখানে যায়। সুইফটের নতুন, অঘোষিত সংস্করণটি কি আছে? এটি কি এমন কোনও ফাংশন যা আমি জানতাম না এমনভাবে ব্যবহার করা হচ্ছে?

কীওয়ার্ডটি কী করে some?


যারা এই বিষয় নিয়ে চঞ্চল ছিলেন তাদের জন্য এখানে ভাদিম বুলভিনকে ধন্যবাদ জানানো খুব ধীরে ধীরে এবং ধাপে ধাপে নিবন্ধ। vadimbulavin.com/…
লুস-অলিভিয়ের

উত্তর:


333

some ViewSE-0244 দ্বারা প্রবর্তিত হিসাবে এটি একটি অস্বচ্ছ ফলাফলের ধরণ এবং এক্সকোড ১১ সহ সুইফ্ট 5.1 এ উপলব্ধ You

একজন নিয়মিত জেনেরিক স্থানধারীর থেকে পৃথক যা কলার দ্বারা সন্তুষ্ট:

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?


১. অস্বচ্ছ ফলাফলের ধরণগুলি প্যাটগুলির সাথে ব্যবহার করা যেতে পারে

প্রোটোকলের একটি প্রধান বর্তমান সীমাবদ্ধতা হ'ল প্যাটগুলি (সম্পর্কিত ধরণের প্রোটোকল) প্রকৃত প্রকার হিসাবে ব্যবহার করা যায় না। যদিও এটি এমন একটি বিধিনিষেধ যা ভাষার ভবিষ্যতের সংস্করণে সম্ভবত তুলে নেওয়া হবে, কারণ অস্বচ্ছ ফলাফলের ধরণগুলি কার্যকরভাবে কেবল জেনেরিক স্থানধারক, সেগুলি আজ প্যাটগুলির সাথে ব্যবহার করা যেতে পারে।

এর অর্থ আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

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

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

২. অস্বচ্ছ ফলাফলের ধরণের পরিচয় রয়েছে

যেহেতু অস্বচ্ছ ফলাফলের প্রকারগুলি কার্যকর করে একটি একক কংক্রিটের প্রকারটি ফিরে আসে, সংকলক জানে যে একই ফাংশনে দুটি কল একই ধরণের দুটি মান ফেরত দিতে পারে।

এর অর্থ আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

//   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
}

এর অর্থ এটি দুটি মানের প্রত্যাশা করে যা উভয়ই কংক্রিটের অনুসারে রূপের ধরণের are এমনকি যদি 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বিভিন্ন ধরণের দ্বারা সন্তুষ্ট হতে পারে।


৩. জেনেরিক স্থানধারীদের সাথে অস্পষ্ট ফলাফলের ধরণের রচনাগুলি

নিয়মিত প্রোটোকল-টাইপ করা মানগুলির থেকে পৃথক, অস্বচ্ছ ফলাফলের ধরণগুলি নিয়মিত জেনেরিক স্থানধারীদের সাথে ভালভাবে রচনা করে, উদাহরণস্বরূপ:

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একক-বহিঃপ্রকাশের ক্রিয়াকলাপগুলিতে প্রয়োজন হয় না
অর্থাৎ ইলমানি

3
তবে এর মধ্যে পার্থক্য কী: func makeP() -> some Pএবং func makeP() -> P? আমি প্রস্তাবটি পড়েছি এবং তাদের নমুনাগুলির জন্যও এই পার্থক্যটি দেখতে পাচ্ছি না।
আর্টেম


2
সুইফট টাইপ হ্যান্ডলিং একটি গোলযোগ। এই নির্দিষ্টতাটি কি সত্যিই এমন কিছু যা সংকলন সময়ে পরিচালনা করা যায় না? রেফারেন্সের জন্য সি # দেখুন, এটি সাধারণ বাক্যবিন্যাসের মাধ্যমে এই সমস্ত ক্ষেত্রে নিখুঁতভাবে পরিচালনা করে। সুইফসের অর্থহীনভাবে প্রায় পরিষ্কার হওয়া দরকার কার্গো-কুলিস্ট সিনট্যাক্সটি ভাষাটি সত্যই অবলম্বন করছে। আপনি কি দয়া করে এর জন্য নকশার যুক্তি ব্যাখ্যা করতে পারেন? (যদি আপনার কাছে গিথুব প্রস্তাবের কোনও লিঙ্ক থাকে তবে এটিও ভাল)) সম্পাদনা: কেবলমাত্র শীর্ষে এটি লিঙ্কিত লক্ষ্য করেছেন।
সেক্রেডজিমিটি

2
@ জাস্টমাস্টার সংকলক দুটি অস্বচ্ছ রিটার্ন টাইপকে আলাদা বলে বিবেচনা করবে যদিও উভয়ের জন্য বাস্তবায়ন একই কংক্রিটের প্রকারটি প্রদান করে। অন্য কথায়, নির্দিষ্ট কংক্রিটের ধরণটি কলার থেকে লুকানো থাকে। (এই জাতীয় জিনিসগুলিকে কিছুটা আরও স্পষ্ট করে তোলার জন্য আমি আমার উত্তরটির উত্তরার অর্ধেকের দিকে প্রসারিত করতে চাইছি তবে এটি এখনও মিলেনি)।
হামিশ

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`
}

দ্রষ্টব্য: এই ফাংশনটি আসলে সংকলন করবে না। এটি কারণ 'কিছু' বৈশিষ্ট্য যুক্ত হওয়ার আগে প্রোটোকল যদি 'স্ব' বা জেনেরিক ব্যবহার করে তবে আপনি কোনও প্রোটোকল টাইপ ফেরত দিতে পারবেন না । তবে আসুন আমরা বলতে পারি যে আপনি এটি করতে পারেন ... এটি উপস্থাপন করে মাইডোগ অ্যাবস্ট্রাক্ট টাইপ অ্যানিমালকে, কী ঘটেছিল তা দেখুন

এখন সমস্যাটি আসে যদি আমি এটি করার চেষ্টা করি:

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কিন্তু শ্রেণীর ব্যবহারকারী তা করেন না।

(স্ব-প্রচার অস্বীকার) আমি এই ব্লগ পোস্টটি লিখেছি যা এই নতুন বৈশিষ্ট্যে আরও কিছুটা গভীরতার (এখানে যেমন উদাহরণ) যায় goes


2
সুতরাং আপনার ধারণাটি কলার এই সুবিধাটি নিতে পারেন যে ফাংশনে দুটি কল একই ধরণের ফিরে আসে যদিও কলার জানেন না এটি কী ধরণের?
ম্যাট

1
@ ম্যাটটি মূলত হ্যাঁ ক্ষেত্র ইত্যাদির সাথে একই ব্যবহার করার সময়, কলরকে গ্যারান্টি দেওয়া হয় যে রিটার্নের ধরণটি সর্বদা একই রকম হবে তবে টাইপটি কী তা ঠিক তা প্রকাশ করে না।
ডাউনওয়েট

@ ডাউনগোট নিখুঁত পোস্ট এবং উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। আমি যেমন বুঝতে পারি যে someরিটার্ন টাইপ কাজ করে শরীরের প্রতিবন্ধকতা হিসাবে। সুতরাং someপুরো ফাংশন বডিতে কেবল একটি কংক্রিট টাইপ ফেরত দেওয়া দরকার। উদাহরণস্বরূপ: আছে যদি return randomDogতারপর অন্য সব আয় শুধুমাত্র সঙ্গে কাজ করতে হবে Dog। সমস্ত সুবিধা এই সীমাবদ্ধতা থেকে আসে: প্রাপ্যতা animal1.isSibling(animal2)এবং সংকলনের সুবিধা func animalFromAnimalFamily() -> some Animal(কারণ এখন Selfহুডের অধীনে সংজ্ঞায়িত হয়ে যায়)। এটা কি ঠিক?
আর্টেম

5
এই লাইনটি কেবল আমার প্রয়োজন ছিল, প্রাণী 1 এবং অ্যানিমাল 2 অ্যানিমাল নয়, তবে তারা শ্রেণি যা অ্যানিমাল প্রয়োগ করে, এখন সমস্ত বোধগম্য হয়!
সারা

29

হামিশের উত্তরটি বেশ দুর্দান্ত এবং প্রযুক্তিগত দৃষ্টিকোণ থেকে প্রশ্নের উত্তর দেয়। someঅ্যাপলের সুইফটইউআই টিউটোরিয়ালে কেন কীওয়ার্ডটি এই নির্দিষ্ট জায়গায় ব্যবহার করা হয়েছে এবং কেন এটি অনুসরণ করা ভাল অভ্যাস রয়েছে সে সম্পর্কে আমি কিছু চিন্তা যুক্ত করতে চাই ।

some একটি প্রয়োজন হয় না!

প্রথমত, আপনার 'রিটার্ন টাইপ' অস্বচ্ছ ধরণের হিসাবে ঘোষণা করার দরকার নেইbody । আপনি সর্বদা ব্যবহারের পরিবর্তে কংক্রিটের ধরণটি ফিরিয়ে দিতে পারেন some View

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

এটি পাশাপাশি সংকলন করা হবে। আপনি যখন Viewইন্টারফেসটির দিকে তাকাবেন , আপনি দেখতে পাবেন যে রিটার্নের ধরণটি 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")
        }
    }
}

এটি সংকলন করবে না এবং আপনি ত্রুটিটি পাবেন:

জেনেরিক ধরণের 'ভিস্ট্যাক'-এর উল্লেখের জন্য <...> এ আর্গুমেন্ট দরকার

এর এটা এ কারণে যে এ স্ট্যাক মতামত SwiftUI হয় জেনেরিক ধরন! 💡 (এবং এটি তালিকা এবং অন্যান্য ধারক দেখার ধরণের ক্ষেত্রেও সত্য ))

এটি অনেক অর্থবহ করে কারণ আপনি যে কোনও ধরণের যেকোন সংখ্যক ভিউ প্লাগ করতে পারেন (যতক্ষণ না এটি Viewপ্রোটোকলের সাথে সামঞ্জস্য থাকে )। VStackউপরের দেহে কংক্রিটের ধরণটি আসলে

VStack<TupleView<(Text, Image)>>

পরে যখন আমরা স্ট্যাকটিতে একটি ভিউ যুক্ত করার সিদ্ধান্ত নিই, তখন এর কংক্রিটের ধরণের পরিবর্তন হয়। আমরা যদি প্রথমটির পরে দ্বিতীয় পাঠ্য যোগ করি তবে আমরা পাই get

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

এমনকি যদি আমরা একটি সামান্য পরিবর্তন করি তবে পাঠ্য এবং চিত্রের মধ্যে স্পেসার যুক্ত করার মতো সূক্ষ্ম কিছু, স্ট্যাকের ধরণের পরিবর্তন:

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

আমি যা বলতে পারি, সে কারণেই অ্যাপল তাদের টিউটোরিয়ালে সর্বদা ব্যবহারের জন্য সুপারিশ করে some View, সবচেয়ে সাধারণ অস্বচ্ছ ধরণ যা সমস্ত দর্শনগুলি সন্তুষ্ট করে, যেমনটি bodyফেরতের টাইপ হিসাবে। আপনি প্রত্যেকবার রিটার্নের ধরণটি ম্যানুয়ালি পরিবর্তন না করে আপনি নিজের কাস্টম ভিউয়ের প্রয়োগকরণ / বিন্যাস পরিবর্তন করতে পারেন।


সাপ্লিমেন্ট:

যদি আপনি অস্বচ্ছ ফলাফলের ধরণের আরও স্বজ্ঞাত ধারণা পেতে চান তবে আমি সম্প্রতি একটি নিবন্ধ প্রকাশ করেছি যা পড়ার পক্ষে উপযুক্ত হতে পারে:

Sw সুইফটিউআইতে এটি "কিছু" কী?


2
এই. ধন্যবাদ! হামিশের উত্তরটি সম্পূর্ণ সম্পূর্ণ ছিল, তবে এই উদাহরণগুলিতে কেন এটি ব্যবহার করা হয়েছে তা আপনারাই আমাকে বলছেন।
ক্রিস মার্শাল

আমি "কিছু" ধারণাটি পছন্দ করি। "কিছু" ব্যবহার করা কি আদৌ সংকলনের সময়কে প্রভাবিত করে?
তোফু ওয়ারিয়র

@ মিশা তাই জেনেরিক দৃষ্টিভঙ্গি কিভাবে করবেন? এমন একটি প্রোটোকল যাতে অন্যান্য আচরণগুলির মতামত উত্তর রয়েছে?
theMouk

27

আমি মনে করি এখন পর্যন্ত সমস্ত উত্তর যা অনুপস্থিত তা হ'ল এটি someমূলত ডিএসএল (ডোমেন-নির্দিষ্ট ভাষা) যেমন সুইফটইউআই বা লাইব্রেরি / ফ্রেমওয়ার্কের মতো কিছু ক্ষেত্রে কার্যকর যা ব্যবহারকারীর (অন্যান্য প্রোগ্রামারদের) নিজের থেকে আলাদা হবে।

আপনি সম্ভবত someআপনার সাধারণ অ্যাপ্লিকেশন কোডটিতে কখনও ব্যবহার করতে পারবেন না, সম্ভবত ইনসোফার ব্যতীত এটি জেনেরিক প্রোটোকলটি গুটিয়ে রাখতে পারে যাতে এটি কোনও ধরণের (কেবল কোনও টাইপের সীমাবদ্ধতার পরিবর্তে) হিসাবে ব্যবহার করা যায়। কি কি someতা কম্পাইলারের সামনে একটি সুপারটাইপ ফেকাড রাখার সময় নির্দিষ্ট কিছু কী কী তা সম্পর্কে জ্ঞান রাখতে দেওয়া হয়।

সুইফ্টইউআইতে, আপনি যেখানে ব্যবহারকারী, আপনাকে যা কিছু জানা দরকার তা হ'ল কিছু কিছু some View, যখন পর্দার আড়ালে সমস্ত ধরণের হ্যাঙ্কি-পাঙ্কি যেতে পারে যা থেকে আপনি shালেন । এই অবজেক্টটি আসলে একটি খুব নির্দিষ্ট ধরণের, তবে এটি কখন কী তা আপনার শোনার দরকার নেই। তবুও, কোনও প্রোটোকলের বিপরীতে, এটি একটি সম্পূর্ণ প্রকারের ধরণ, কারণ যেখানেই এটি প্রদর্শিত হয় এটি নির্দিষ্ট নির্দিষ্ট পূর্ণ-ধরণের ধরণের জন্য কেবল একটি মুখোমুখি।

সুইফটইউআইয়ের ভবিষ্যতের সংস্করণে, যেখানে আপনি একটির প্রত্যাশা করছেন some View, বিকাশকারীরা সেই নির্দিষ্ট বস্তুর অন্তর্নিহিত ধরণের পরিবর্তন করতে পারে। তবে এটি আপনার কোডটি ভাঙবে না, কারণ আপনার কোডটি কখনই প্রথম স্থানে অন্তর্নিহিত ধরণের কথা উল্লেখ করে না।

সুতরাং, someকার্যকরভাবে একটি সুপারক্লাসের মতো একটি প্রোটোকল তৈরি করে। এটি প্রায় সত্যিকারের অবজেক্টের ধরণ, যদিও যথেষ্ট নয় (উদাহরণস্বরূপ, একটি প্রোটোকলের পদ্ধতির ঘোষণাপত্রটি ফিরে আসতে পারে না some)।

সুতরাং আপনি যদি someকোনও কিছুর জন্য ব্যবহার করতে যাচ্ছেন তবে সম্ভবত আপনি যদি অন্যের দ্বারা ব্যবহারের জন্য ডিএসএল বা ফ্রেমওয়ার্ক / লাইব্রেরি লিখছিলেন এবং আপনি অন্তর্নিহিত ধরণের বিবরণটি মুখোশ করতে চেয়েছিলেন তবে এটি সম্ভবত সম্ভবত । এটি অন্যদের ব্যবহারের জন্য আপনার কোডকে আরও সহজ করে দেবে এবং কোডটি ভঙ্গ না করে আপনাকে প্রয়োগের বিশদ পরিবর্তন করতে দেয়।

তবে আপনি এটিকে নিজের কোডের একটি অঞ্চলে আপনার কোডের অন্য একটি অঞ্চলে সমাহিত প্রয়োগের বিশদ থেকে আপনার কোডের একটি অঞ্চল রক্ষার উপায় হিসাবেও ব্যবহার করতে পারেন।


22

someসুইফট 5.1 (থেকে শব্দ দ্রুতগতি-বিবর্তন প্রস্তাব ) একটি রিটার্ন টাইপ হিসাবে একটি প্রোটোকল সাথে ব্যবহার করা হয়।

এক্সকোড 11 রিলিজ নোটগুলি এটির মতো উপস্থাপন করে:

ফাংশনগুলি এখন ঠিকঠাক ফেরতের প্রকার নির্দিষ্ট করে না দিয়ে কী প্রোটোকল গ্রহণ করে তা ঘোষণা করে তাদের কংক্রিট রিটার্নের প্রকারটি আড়াল করতে পারে:

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

ফাংশনটি কল করে এমন কোডগুলি প্রোটোকলের ইন্টারফেস ব্যবহার করতে পারে তবে অন্তর্নিহিত ধরণের মধ্যে দৃশ্যমানতা নেই। ( এসই -0244, 40538331)

উপরের উদাহরণে, আপনাকে বলার দরকার নেই যে আপনি একটি ফেরত যাচ্ছেন Array। এটি আপনাকে এমন একটি জেনেরিক টাইপও ফিরিয়ে দিতে দেয় যা স্রেফ মেনে চলে Collection


আপনার মুখোমুখি হতে পারে এমন সম্ভাব্য ত্রুটিটিও নোট করুন:

'কিছু' রিটার্নের ধরণগুলি কেবলমাত্র আইওএস 13.0.0 বা আরও নতুনতে উপলভ্য

এর অর্থ হ'ল someআইওএস 12 এবং এর আগে এড়ানোর জন্য আপনার প্রাপ্যতাটি ব্যবহার করার কথা :

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

1
এই কেন্দ্রীভূত উত্তরের জন্য এবং
এক্সকোড

1
someআইওএস 12 এবং এর আগে এড়ানোর জন্য আপনার প্রাপ্যতাটি ব্যবহার করার কথা । যতক্ষণ আপনি করেন, আপনার ভাল হওয়া উচিত। সমস্যাটি কেবল এটিই যে সংকলক আপনাকে এটি করতে সতর্ক করে না।
ম্যাট

2
কোর, ঠিক যেমনটি আপনি উল্লেখ করেছেন, সংক্ষিপ্ত অ্যাপল বিবরণটি এটিকে সমস্ত ব্যাখ্যা করে: কার্যকারিতা এখন তাদের কংক্রিট রিটার্নের ধরণটি সঠিক প্রেরণের ধরণটি নির্দিষ্ট করে না দিয়ে প্রোটোকলগুলির সাথে কী উপযুক্ত তা ঘোষণা করে আড়াল করতে পারে। এবং তারপরে কোডটি ফাংশন প্রোটোকল ইন্টারফেস ব্যবহার করতে পারে। ঝরঝরে এবং তারপর কিছু।
ফ্যাটি

"কিছু" শব্দটি ব্যবহার না করে এটি (কংক্রিটের রিটার্নের ধরণটি গোপন করা) ইতিমধ্যে সম্ভব। এটি পদ্ধতির স্বাক্ষরে "কিছু" যুক্ত করার প্রভাব ব্যাখ্যা করে না।
ভিন্স ও'সুলিভান

@ ভিনসো সুলিভান someএই প্রদত্ত কোডের নমুনায় কীওয়ার্ডটি স্যুইফ্ট 5.0 বা সুইফট 4.2- তে সরিয়ে ফেলা সম্ভব নয় । ত্রুটিটি হ'ল: " প্রোটোকল 'সংগ্রহ' কেবল জেনেরিক বাধা হিসাবে ব্যবহার করা যেতে পারে কারণ এটির স্ব বা সম্পর্কিত ধরণের প্রয়োজনীয়তা রয়েছে "
Curur

2

'কিছু' অর্থ অস্বচ্ছ ধরণ। সুইফটুইতে ভিউকে একটি প্রোটোকল হিসাবে ঘোষণা করা হয়

@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 }
}

আপনি যখন স্ট্রাক্ট হিসাবে আপনার দৃষ্টিভঙ্গি তৈরি করেন, আপনি ভিউ প্রোটোকলের সাথে সামঞ্জস্য করেন এবং বলে যে ভের বডি এমন কিছু প্রত্যাবর্তন করবে যা ভিউ প্রোটোকলকে নিশ্চিত করবে। এটি জেনেরিক প্রোটোকল বিমূর্তির মতো যেখানে আপনাকে কংক্রিটের ধরণ নির্ধারণ করতে হবে না।


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()
}

উপরে ব্যবহারিক ব্যবহার রয়েছে, এর জন্য সুইফটইউআই-তে ব্যাপকভাবে ব্যবহৃত হয় 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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.