কীভাবে সুইফটে জেনেরিক প্রোটোকল তৈরি করবেন?


85

আমি এমন একটি পদ্ধতি সহ একটি প্রোটোকল তৈরি করতে চাই যা জেনেরিক ইনপুট নেয় এবং জেনেরিক মান দেয়।

এটি আমি এ পর্যন্ত চেষ্টা করেছি তবে এটি সিনট্যাক্স ত্রুটি তৈরি করে।

অঘোষিত শনাক্তকারী টি।

আমি কি ভুল করছি?

protocol ApiMapperProtocol {
    func MapFromSource(T) -> U
}

class UserMapper: NSObject, ApiMapperProtocol {
    func MapFromSource(data: NSDictionary) -> UserModel {
        var user = UserModel() as UserModel
        var accountsData:NSArray = data["Accounts"] as NSArray     
        return user
    } 
}

: দয়া করে আমার উত্তর পরীক্ষা stackoverflow.com/a/54900296/3564632
denis_lor

উত্তর:


143

প্রোটোকলের ক্ষেত্রে এটি কিছুটা আলাদা। অ্যাপলের ডকুমেন্টেশনে "অ্যাসোসিয়েটেড প্রকারগুলি" দেখুন ।

আপনি আপনার উদাহরণে এটি কীভাবে ব্যবহার করেন

protocol ApiMapperProtocol {
    associatedtype T
    associatedtype U
    func MapFromSource(_:T) -> U
}

class UserMapper: NSObject, ApiMapperProtocol {
    typealias T = NSDictionary
    typealias U = UserModel

    func MapFromSource(_ data:NSDictionary) -> UserModel {
        var user = UserModel()
        var accountsData:NSArray = data["Accounts"] as NSArray
        // For Swift 1.2, you need this line instead
        // var accountsData:NSArray = data["Accounts"] as! NSArray
        return user
    }
}

4
নোট করুন যে অ্যাপিম্প্পারপ্রোটোকলের একমাত্র উদ্দেশ্য জেনেরিক সীমাবদ্ধতার জন্য ব্যবহার করা। আপনি x লিখতে পারেন এমনটি নয়: ApiMapperProtocol = UserMapper ()
বেন

19
কেন অ্যাপল সব কিছুকে এত স্বজ্ঞাত করে তুলতে জোর দিয়েছিলেন?
ডিউসপ্রোগ্রামার

@ বেন কীভাবে এক্স অর্জন করবে x: এপিএম্প্পারপ্রোটোকল = ইউজারম্যাপার () এই ক্ষেত্রে?
denis_lor

@denis_lor যদি xস্থানীয় হয় তবে আপনার স্পষ্টরূপে এর প্রকারটি বলার দরকার নেই, তাই let x = UserMapper()
বেন লেগিগেরো

4
@BenLeggiero আমি শুধু পাওয়া আউট আপনার মত ধরা যাক x করতে পারেন: ApiMapperProtocol = UserMapper () যদি মধ্যম জেনেরিক বর্গ একটি ব্যবহার করছে: stackoverflow.com/a/54900296/3564632
denis_lor

21

লু ফ্রাঙ্কোর উত্তরটি খানিকটা ব্যাখ্যা করার জন্য , আপনি যদি কোনও বিশেষ পদ্ধতি ব্যবহার করে এমন কোনও পদ্ধতি তৈরি করতে চান তবে ApiMapperProtocolআপনি তা এভাবেই করুন:

protocol ApiMapperProtocol {
    associatedtype T
    associatedtype U
    func mapFromSource(T) -> U
}

class UserMapper: NSObject, ApiMapperProtocol {
    // these typealiases aren't required, but I'm including them for clarity
    // Normally, you just allow swift to infer them
    typealias T = NSDictionary 
    typealias U = UserModel

    func mapFromSource(data: NSDictionary) -> UserModel {
        var user = UserModel()
        var accountsData: NSArray = data["Accounts"] as NSArray
        // For Swift 1.2, you need this line instead
        // var accountsData: NSArray = data["Accounts"] as! NSArray
        return user
    }
}

class UsesApiMapperProtocol {
    func usesApiMapperProtocol<
        SourceType,
        MappedType,
        ApiMapperProtocolType: ApiMapperProtocol where
          ApiMapperProtocolType.T == SourceType,
          ApiMapperProtocolType.U == MappedType>(
          apiMapperProtocol: ApiMapperProtocolType, 
          source: SourceType) -> MappedType {
        return apiMapperProtocol.mapFromSource(source)
    }
}

UsesApiMapperProtocolপ্রদত্ত সাথে কেবল SourceTypeসামঞ্জস্যপূর্ণ গ্রহণের জন্য এখন গ্যারান্টিযুক্ত ApiMapperProtocol:

let dictionary: NSDictionary = ...
let uses = UsesApiMapperProtocol()
let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper()
    source: dictionary)

এটি একটি খুব সুন্দর লেখা, upvated। কয়েকটা মূর্খ প্রশ্ন: কেন তারা as!কেবল asসুইফট ১.২ এর পরিবর্তে ব্যবহারের সিদ্ধান্ত নিয়েছে ? দ্বিতীয়: আপনি কি আমাকে বলতে পারেন যে প্রোটোকলের সাথে সঙ্গতিপূর্ণ ক্লাসে আমাদের type aliasআবার কেন (অর্থাৎ typealias T = NSDictionary typealias U = UserModel) সংজ্ঞা দেওয়া দরকার ? আগাম ধন্যবাদ.
আনহিলিগ

আমি জানি না কেন তারা থেকে সুইচড না asকরতে as!। ডিভফোরামগুলি পরীক্ষা করুন।
সীমানা

typealias T=NSDictionaryএবং typealias U=UserModelপ্রয়োজন হয় না। আমি প্রতিফলিত করার জন্য উদাহরণটি আপডেট করেছি।
সীমানা

4
যেমন! এটি ব্যর্থ হতে পারে নির্দেশ করতে। এটি বিকাশকারীকে আরও পরিষ্কার করে তোলে।
user965972

এটি উত্তরের নীচে।
সীমানা

4

let userMapper: ApiMapperProtocol = UserMapper()জেনেরিক অর্জন এবং পাশাপাশি এটি ঘোষণার জন্য আপনাকে প্রোটোকল অনুসারে একটি জেনেরিক ক্লাস থাকতে হবে যা জেনেরিক উপাদানটি দেয়।

protocol ApiMapperProtocol {
    associatedtype I
    associatedType O
    func MapFromSource(data: I) -> O
}

class ApiMapper<I, O>: ApiMapperProtocol {
    func MapFromSource(data: I) -> O {
        fatalError() // Should be always overridden by the class
    }
}

class UserMapper: NSObject, ApiMapper<NSDictionary, UserModel> {
    override func MapFromSource(data: NSDictionary) -> UserModel {
        var user = UserModel() as UserModel
        var accountsData:NSArray = data["Accounts"] as NSArray     
        return user
    } 
}

এখন আপনি সেই userMapperহিসাবে উল্লেখ করতে পারেন ApiMapperযার প্রতি নির্দিষ্ট প্রয়োগ রয়েছে UserMapper:

let userMapper: ApiMapper = UserMapper()
let userModel: UserModel = userMapper.MapFromSource(data: ...)

4
এক্ষেত্রে প্রোটোকল থাকার কী লাভ? এটি ঘোষণাপত্রে ব্যবহৃত হয়নি userMapper
alekop

-1

জেনেরিক প্রোটোকলটি কীভাবে তৈরি এবং ব্যবহার করা যায়

প্রোটোকল জেনেরিক {

associatedtype T
associatedtype U

func operation(_ t:T)->U

}

// জেনেরিক প্রোটোকল ব্যবহার করুন

কাঠামো পরীক্ষা: জেনেরিক {

typealias T = UserModel
typealias U = Any

func operation(_ t: UserModel)->Any {
    let dict = ["name":"saurabh"]
    return dict
    
} 

}


-3

আপনি টাইপ-ইরেজরের সাথে টেম্পলেট পদ্ধতি ব্যবহার করতে পারেন ...

protocol HeavyDelegate : class {
  func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R
}  

class Heavy<P, R> {
    typealias Param = P
    typealias Return = R
    weak var delegate : HeavyDelegate?  
    func inject(p : P) -> R? {  
        if delegate != nil {
            return delegate?.heavy(self, shouldReturn: p)
        }  
        return nil  
    }
    func callMe(r : Return) {
    }
}
class Delegate : HeavyDelegate {
    typealias H = Heavy<(Int, String), String>

    func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R {
        let h = heavy as! H
        h.callMe("Hello")
        print("Invoked")
        return "Hello" as! R
    }  
}

let heavy = Heavy<(Int, String), String>()
let delegate = Delegate()
heavy.delegate = delegate
heavy.inject((5, "alive"))

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