প্রোটোকল কেবল জেনেরিক সীমাবদ্ধতা হিসাবে ব্যবহার করা যেতে পারে কারণ এর স্ব বা সংযুক্ত টাইপের প্রয়োজনীয়তা রয়েছে


102

আমার কাছে একটি প্রোটোকল রিকুয়েস্টটাইপ রয়েছে এবং এটি নীচের মতো টাইপ মডেলটি যুক্ত করেছে।

public protocol RequestType: class {

    associatedtype Model
    var path: String { get set }

}

public extension RequestType {

    public func executeRequest(completionHandler: Result<Model, NSError> -> Void) {
        request.response(rootKeyPath: rootKeyPath) { [weak self] (response: Response<Model, NSError>) -> Void in
            completionHandler(response.result)
            guard let weakSelf = self else { return }
            if weakSelf.logging { debugPrint(response) }
        }
    }

}

এখন আমি সমস্ত ব্যর্থ অনুরোধের একটি সারি তৈরি করার চেষ্টা করছি।

public class RequestEventuallyQueue {

    static let requestEventuallyQueue = RequestEventuallyQueue()
    let queue = [RequestType]()

}

তবে আমি লাইনে ত্রুটি let queue = [RequestType]()পেয়েছি যে প্রোটোকল রিকোয়েস্টটাইপটি কেবল জেনেরিক সীমাবদ্ধতা হিসাবে ব্যবহার করা যেতে পারে কারণ এতে স্ব বা সংযুক্ত টাইপের প্রয়োজনীয়তা রয়েছে।

উত্তর:


152

মনে করুন মুহুর্তের জন্য আমরা আপনার প্রোটোকলটি এমন একটি রুটিন যুক্ত করতে যুক্ত করি যা সম্পর্কিত ধরণের ব্যবহার করে:

public protocol RequestType: class {
    associatedtype Model
    var path: String { get set }

    func frobulateModel(aModel: Model)
}

এবং সুইফ্ট আপনাকে RequestTypeযেভাবে চান তার একটি অ্যারে তৈরি করতে দেয়। আমি অনুরোধের ধরণের একটি অ্যারে একটি ফাংশনে পাস করতে পারি:

func handleQueueOfRequests(queue: [RequestType]) {
    // frobulate All The Things!

    for request in queue {
       request.frobulateModel(/* What do I put here? */)
    }
}

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

একই সাথে এটি নিখুঁত ধারণা তৈরি করে, উদাহরণস্বরূপ, RequestTypeযখন আমরা জানি যে এগুলি সমস্তই ব্যবহার করে তখন একটি অ্যারে তৈরি করে LegoModel। এটি যুক্তিসঙ্গত বলে মনে হয় এবং এটি হয় তবে এটি প্রকাশ করার জন্য আপনার কিছু উপায় প্রয়োজন need

এটি করার একটি উপায় হ'ল একটি শ্রেণি তৈরি করা (বা স্ট্রাক্ট, বা এনাম) যা বিমূর্ত মডেল টাইপের নামের সাথে একটি আসল প্রকারকে যুক্ত করে:

class LegoRequestType: RequestType {
  typealias Model = LegoModel

  // Implement protocol requirements here
}

এখন এটির অ্যারে ঘোষণা করা পুরোপুরি যুক্তিসঙ্গত LegoRequestTypeকারণ আমরা যদি frobulateতাদের সকলের কাছে চাইতাম তবে আমরা জানতাম যে আমাদের LegoModelপ্রত্যেকবার পাস করতে হবে ।

অ্যাসোসিয়েটেড টাইপের সাথে এই উপকারগুলি যে কোনও প্রোটোকল তৈরি করে যা সেগুলি বিশেষ ব্যবহার করে। সুইফ্ট স্ট্যান্ডার্ড লাইব্রেরিতে এর মধ্যে প্রোটোকল রয়েছে উল্লেখযোগ্য Collectionবা Sequence

আপনি যে জিনিস বাস্তবায়ন একটি অ্যারের তৈরি করতে অনুমতি দিতে Collectionপ্রোটোকল বা বিষয় আছে যা ক্রম প্রটোকল বাস্তবায়ন একটি সেট, স্ট্যান্ডার্ড লাইব্রেরী একটি কৌশল struct হয় ধরনের তৈরি করতে "টাইপ-ইরেজিওর" বলা নিয়োগ AnyCollection<T>বা AnySequence<T>। টাইপ-ইরেজ টেকনিকটি স্ট্যাক ওভারফ্লো উত্তরে ব্যাখ্যা করার চেয়ে জটিল তবে আপনি যদি ওয়েবটি অনুসন্ধান করেন তবে এটি সম্পর্কে প্রচুর নিবন্ধ রয়েছে।

আমি ইউটিউবে প্রোটোকল উইথ অ্যাসোসিয়েটেড টাইপস (প্যাটস)অ্যালেক্স গ্যালাগারের একটি ভিডিওর প্রস্তাব দিতে পারি ।


40
"আপনার সমাধানটি খুব জেনেরিক " 😂
অ্যাডল্ফো

6
এটি এই সমস্যার জন্য আমি যে সেরা ব্যাখ্যা দেখেছি তার মধ্যে একটি
কেয়াব 42

4
খুব ভাল ব্যাখ্যা, তাই একক উত্তর।
আলমাস আদিলবেক

4
ফ্রোবুলেট বলতে কী বোঝায়?
মোফাওয়াও

4
এই উত্তরটি ফ্রোবুলেট শব্দের ব্যবহার বন্ধ করে দেওয়ার দুর্দান্ত অজুহাত ছিল।
স্কটিব্ল্যাডেস

18

সুইফ্ট 5.1 থেকে - এক্সকোড 11

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

এটি কল্পনা করুন:

protocol ProtocolA {
    associatedtype number
}

class ClassA: ProtocolA {
    typealias number = Double
}

সুতরাং নিম্নলিখিতটি ত্রুটি উত্পন্ন করে:

var objectA: ProtocolA = ClassA() /* Protocol can only be used as a generic constraint because it has Self or associatedType requirements */

তবে প্রকারটির আগে কীওয়ার্ড যুক্ত করে ধরণের অস্বচ্ছ তৈরি করা someসমস্যার সমাধান করবে এবং সাধারণত আমরা যা চাই তা কেবল এটির জন্য:

var objectA: some ProtocolA = ClassA()

4

আপনার কোড ডিজাইনের সামান্য পরিবর্তন এটি সম্ভব করে তুলতে পারে। আপনার প্রোটোকল শ্রেণিবিন্যাসের শীর্ষে একটি খালি, অ-সম্পর্কিত টাইপ, প্রোটোকল যুক্ত করুন। এটার মত...

public protocol RequestTypeBase: class{}

public protocol RequestType: RequestTypeBase {

    associatedtype Model
    var path: Model? { get set } //Make it type of Model

}
public class RequestEventuallyQueue {

    static let requestEventuallyQueue = RequestEventuallyQueue()
    var queue = [RequestTypeBase]() //This has to be 'var' not 'let'

}

অন্য উদাহরণ, প্রোটোকল রিকোয়েস্টটাইপ থেকে প্রাপ্ত ক্লাসগুলির সাথে, একটি সারি তৈরি করা এবং যথাযথ প্রিন্ট করার জন্য সারিটি কোনও ফাংশনে সরিয়ে দেওয়া

public class RequestA<AType>: RequestType{
   public typealias Model = AType
   public var path: AType?
}
public class RequestB<BType>: RequestType{
   public typealias Model = BType
   public var path: BType?
}

var queue = [RequestTypeBase]()

let aRequest: RequestA = RequestA<String>()
aRequest.path = "xyz://pathA"

queue.append(aRequest)

let bRequest: RequestB = RequestB<String>()
bRequest.path = "xyz://pathB"

queue.append(bRequest)

let bURLRequest: RequestB = RequestB<URL>()
bURLRequest.path = URL(string: "xyz://bURLPath")

queue.append(bURLRequest)

func showFailed(requests: [RequestTypeBase]){

    for request in requests{
        if let request = request as? RequestA<String>{
            print(request.path!)
        }else if let request = request as? RequestB<String>{
            print(request.path!)
        }else if let request = request as? RequestB<URL>{
            print(request.path!)
        }

    }
}

showFailed(requests: queue)

4

সুইফট 5.1

একটি সম্পর্কিত প্রকার এবং বেস প্রোটোকল প্রয়োগ করে আপনি জেনেরিক প্রোটোকল কীভাবে ব্যবহার করতে পারেন তার একটি উদাহরণ :

import Foundation

protocol SelectOptionDataModelProtocolBase: class{}

protocol SelectOptionDataModelProtocol: SelectOptionDataModelProtocolBase {
    associatedtype T
    
    var options: Array<T> { get }
    
    var selectedIndex: Int { get set }
    
}

class SelectOptionDataModel<A>: SelectOptionDataModelProtocol {
    typealias T = A
    
    var options: Array<T>
    
    var selectedIndex: Int
    
    init(selectedIndex _selectedIndex: Int, options _options: Array<T>) {
        self.options = _options
        self.selectedIndex = _selectedIndex
    }
    
}

এবং একটি উদাহরণ দেখুন নিয়ন্ত্রক:

import UIKit

struct Car {
    var name: String?
    var speed: Int?
}

class SelectOptionViewController: UIViewController {
    
    // MARK: - IB Outlets
    
    // MARK: - Properties
    
    var dataModel1: SelectOptionDataModelProtocolBase?
    var dataModel2: SelectOptionDataModelProtocolBase?
    var dataModel3: SelectOptionDataModelProtocolBase?

    // MARK: - Initialisation
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init() {
        self.init(title: "Settings ViewController")
    }
    
    init(title _title: String) {
        super.init(nibName: nil, bundle: nil)
        
        self.title = _title
        
        self.dataModel1 = SelectOptionDataModel<String>(selectedIndex: 0, options: ["option 1", "option 2", "option 3"])
        self.dataModel2 = SelectOptionDataModel<Int>(selectedIndex: 0, options: [1, 2, 3])
        self.dataModel3 = SelectOptionDataModel<Car>(selectedIndex: 0, options: [Car(name: "BMW", speed: 90), Car(name: "Toyota", speed: 60), Car(name: "Subaru", speed: 120)])

    }
    
    // MARK: - IB Actions
    
    
    // MARK: - View Life Cycle

    
}

0

এই ত্রুটি নিম্নলিখিত পরিস্থিতিতেও ঘটতে পারে:

protocol MyProtocol {
    assosciatedtype SomeClass
    func myFunc() -> SomeClass
}

struct MyStuct {
    var myVar = MyProtocol
}

এই ক্ষেত্রে, সমস্যাটি সমাধান করতে আপনাকে যা করতে হবে তা হ'ল জেনারিক ব্যবহার করা:

protocol MyProtocol {
    assosciatedtype SomeClass
    func myFunc() -> SomeClass
}

struct MyStuct<T: MyProtocol> {
    var myVar = T
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.