সুইফটে, আমি কীভাবে একটি নির্দিষ্ট ধরণের ভেরিয়েবল ঘোষণা করতে পারি যা এক বা একাধিক প্রোটোকলের সাথে সঙ্গতিপূর্ণ?


97

সুইফটে আমি ভেরিয়েবলের প্রকারটি নীচে ঘোষণা করে স্পষ্ট করে সেট করতে পারি:

var object: TYPE_NAME

আমরা যদি এটিকে আরও একধাপ এগিয়ে নিয়ে যেতে চাই এবং একাধিক প্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন একটি ভেরিয়েবল ঘোষণা করি যা আমরা protocolঘোষণাটি ব্যবহার করতে পারি :

var object: protocol<ProtocolOne,ProtocolTwo>//etc

আমি যদি এমন কোনও বিষয় ঘোষণা করতে চাই যা একটি বা একাধিক প্রোটোকলের সাথে সঙ্গতিপূর্ণ হয় এবং এটি একটি নির্দিষ্ট বেস শ্রেণীরও হয়? অবজেক্টিভ-সি সমতুল্যটি এর মতো দেখতে পাবেন:

NSSomething<ABCProtocolOne,ABCProtocolTwo> * object = ...;

সুইফটে আমি এটির মতো দেখতে আশা করব:

var object: TYPE_NAME,ProtocolOne//etc

এটি আমাদের বেস ধরণের বাস্তবায়ন এবং প্রোটোকলটিতে সংজ্ঞায়িত যুক্ত ইন্টারফেসের সাথে ডিল করতে সক্ষম হওয়ার নমনীয়তা দেয়।

আমি নিখোঁজ হতে পারে এমন আরও কিছুর উপায় আছে?

উদাহরণ

উদাহরণ হিসাবে, বলুন আমার একটি UITableViewCellফ্যাক্টরি রয়েছে যা একটি প্রোটোকলের সাথে খাপ খায় এমন সেলগুলি ফিরিয়ে দেওয়ার জন্য দায়বদ্ধ। আমরা সহজেই একটি জেনেরিক ফাংশন সেটআপ করতে পারি যা কোনও প্রোটোকলের সাথে সঙ্গতিপূর্ণ সেলগুলি প্রদান করে:

class CellFactory {
    class func createCellForItem<T: UITableViewCell where T:MyProtocol >(item: SpecialItem,tableView: UITableView) -> T {
        //etc
    }
}

পরবর্তীতে আমি প্রকার এবং প্রোটোকল উভয়কেই উপকার করতে গিয়ে এই কোষগুলি সনাক্ত করতে চাই

var cell: MyProtocol = CellFactory.createCellForItem(somethingAtIndexPath) as UITableViewCell

এটি একটি ত্রুটি ফেরায় কারণ একটি টেবিল ভিউ সেল প্রোটোকলের সাথে খাপ খায় না ...

আমি উল্লেখ করতে সক্ষম হতে চাই যে ঘরটি একটি UITableViewCellএবং MyProtocolভেরিয়েবল ঘোষণায় মেনে চলে?

ন্যায্যতা

আপনি যদি কারখানার প্যাটার্নটির সাথে পরিচিত হন তবে এটি নির্দিষ্ট ইন্টারফেস প্রয়োগকারী কোনও নির্দিষ্ট শ্রেণীর অবজেক্টগুলিকে ফিরিয়ে দিতে সক্ষম হওয়ার প্রসঙ্গে তা বোঝাতে পারে।

ঠিক আমার উদাহরণের মতো, কখনও কখনও আমরা এমন ইন্টারফেসগুলি সংজ্ঞায়িত করতে চাই যা কোনও নির্দিষ্ট অবজেক্টের সাথে প্রয়োগ করার সময় সার্থক হয়। আমার টেবিল ভিউ সেলটির উদাহরণটি এরকম একটি ন্যায়সঙ্গততা।

সরবরাহিত ধরণটি উল্লিখিত ইন্টারফেসের সাথে যথাযথভাবে সামঞ্জস্য না করে, কারখানাটি যে জিনিসটি দেয় তা হ'ল এবং তাই আমি বেস বর্গের ধরণ এবং ঘোষিত প্রোটোকল ইন্টারফেস উভয়ের সাথে যোগাযোগের ক্ষেত্রে নমনীয়তা চাই would


দুঃখিত, তবে তাড়াহুড়ো করে কী বলছে। প্রকারগুলি কী কী প্রোটোকল অনুসারে তা ইতিমধ্যে জানে। শুধু কি টাইপ ব্যবহার না?
কিরস্টাইন

4
@ কিরস্টেইনগুলি যদি না কারখানা থেকে টাইপটি না ফেরানো হয় এবং এটি সাধারণ বেস শ্রেণীর সাথে জেনেরিক ধরণ না হয়
ড্যানিয়েল গালাসকো

সম্ভব হলে দয়া করে একটি উদাহরণ দিন।
কিরস্টাইন

NSSomething<ABCProtocolOne,ABCProtocolTwo> * object = ...;। এই অবজেক্টটি বেশ অকেজো বলে মনে হচ্ছে NSSomethingকারণ এটি ইতিমধ্যে কী করে তা জানে knows এটা প্রোটোকল মধ্যে এক সাথে সামঞ্জস্য না থাকলে <>আপনি পাবেন unrecognised selector ...বিপর্যস্ত। এটি কোনও প্রকারের সুরক্ষা দেয় না।
কিরস্টাইন

@ কিরস্টেইনস দয়া করে আমার উদাহরণটি আবার দেখুন, যখন আপনি জানেন যে আপনার কারখানাটি যে বস্তুটি সরবরাহ করে তা কোনও নির্দিষ্ট বেস শ্রেণীর একটি নির্দিষ্ট প্রোটোকলের সাথে
খাপ খায়

উত্তর:


73

সুইফট 4-তে এখন কোনও ভেরিয়েবলটি ঘোষণা করা সম্ভব যা কোনও প্রকারের একটি উপশ্রেণী এবং একই সাথে এক বা একাধিক প্রোটোকল প্রয়োগ করে।

var myVariable: MyClass & MyProtocol & MySecondProtocol

একটি alচ্ছিক পরিবর্তনশীল করতে:

var myVariable: (MyClass & MyProtocol & MySecondProtocol)?

বা কোনও পদ্ধতির পরামিতি হিসাবে:

func shakeEm(controls: [UIControl & Shakeable]) {}

অ্যাপল 402 সেশনে ডাব্লুডাব্লুডিসি 2017 এ এটি ঘোষণা করেছিল : সুইফটে নতুন কী

দ্বিতীয়ত, আমি ক্লাস এবং প্রোটোকল রচনা সম্পর্কে কথা বলতে চাই। সুতরাং, আমি এখানে একটি UI উপাদানটির জন্য এই কাঁপানো প্রোটোকলটি প্রবর্তন করেছি যা নিজের দিকে দৃষ্টি আকর্ষণ করার জন্য সামান্য কাঁপানো প্রভাব দিতে পারে। এবং আমি এগিয়ে গিয়েছি এবং কিছুটা ইউআইকিট ক্লাসকে প্রসারিত করেছি যাতে এই শেক কার্যকারিতাটি সরবরাহ করে। এবং এখন আমি এমন কিছু লিখতে চাই যা সহজ মনে হয়। আমি কেবল এমন একটি ফাংশন লিখতে চাই যা কাঁপতে পারা এমন একগুচ্ছ নিয়ন্ত্রণ নেয় এবং তাদের দৃষ্টি আকর্ষণ করতে সক্ষম হওয়াগুলিকে নাড়া দেয়। আমি এখানে কোন ধরণের লিখতে পারি? এটি আসলে হতাশাবোধ এবং কৃপণ। সুতরাং, আমি একটি ইউআই নিয়ন্ত্রণ ব্যবহার করার চেষ্টা করতে পারি। তবে সমস্ত ইউআই নিয়ন্ত্রণ এই গেমটিতে কাঁপানো যায় না। আমি কাঁপানোর চেষ্টা করতে পারি, তবে সমস্ত শাককেই ইউআই নিয়ন্ত্রণ নয়। এবং সুইফ্ট 3-তে এটি উপস্থাপনের জন্য আসলে কোনও ভাল উপায় নেই।সুইফট 4 কোনও শ্রেণি রচনা করার জন্য যে কোনও সংখ্যক প্রোটোকল ধারণার প্রবর্তন করে।


4
কেবল সুইফট বিবর্তন প্রস্তাবের একটি লিঙ্ক যুক্ত করুন github.com/apple/swift-evolution/blob/master/proposals/…
ড্যানিয়েল গালাসকো

ধন্যবাদ ফিলিপ!
ওমর আলবেইক

যদি এই ধরণের একটি alচ্ছিক পরিবর্তনশীল প্রয়োজন?
ব্যচাস্লাভ গের্চিকভ

4
@ ভাইচাস্লাভ গ্রাচিকোভ: আপনি চারপাশে প্রথম বন্ধনী স্থাপন করতে পারেন এবং তারপরে প্রশ্ন চিহ্নটি এটি করতে পারেন: মাই ভ্যারিয়েবল: (মাই ক্লাস এবং মাইপ্রোটোকল এবং মাইসেকেন্ডপ্রোটোকল)?
ফিলিপ অটো

30

আপনি ভেরিয়েবলের মতো ঘোষণা করতে পারবেন না

var object:Base,protocol<ProtocolOne,ProtocolTwo> = ...

যেমন ফাংশন রিটার্ন টাইপ ঘোষণা না

func someFunc() -> Base,protocol<MyProtocol,Protocol2> { ... }

আপনি এটির মতো কোনও ফাংশন প্যারামিটার হিসাবে ঘোষণা করতে পারেন তবে এটি মূলত আপ-কাস্টিং।

func someFunc<T:Base where T:protocol<MyProtocol1,MyProtocol2>>(val:T) {
    // here, `val` is guaranteed to be `Base` and conforms `MyProtocol` and `MyProtocol2`
}

class SubClass:BaseClass, MyProtocol1, MyProtocol2 {
   //...
}

let val = SubClass()
someFunc(val)

এখন পর্যন্ত, আপনি যা করতে পারেন তা হ'ল:

class CellFactory {
    class func createCellForItem(item: SpecialItem) -> UITableViewCell {
        return ... // any UITableViewCell subclass
    }
}

let cell = CellFactory.createCellForItem(special)
if let asProtocol = cell as? protocol<MyProtocol1,MyProtocol2> {
    asProtocol.protocolMethod()
    cell.cellMethod()
}

এটির সাথে, প্রযুক্তিগতভাবে cellঅভিন্ন asProtocol

তবে, সংকলক হিসাবে cellকেবলমাত্র ইন্টারফেস রয়েছে UITableViewCell, তবে asProtocolকেবল প্রোটোকল ইন্টারফেস রয়েছে। সুতরাং, যখন আপনি UITableViewCellএর পদ্ধতিগুলি কল করতে চান , আপনাকে cellভেরিয়েবল ব্যবহার করতে হবে । আপনি যখন প্রোটোকল পদ্ধতিতে কল করতে চান তখন asProtocolভেরিয়েবল ব্যবহার করুন।

আপনি যদি নিশ্চিত হন যে ঘরটি প্রোটোকলগুলিকে মেনে চলে তবে আপনাকে ব্যবহার করতে হবে না if let ... as? ... {}। পছন্দ:

let cell = CellFactory.createCellForItem(special)
let asProtocol = cell as protocol<MyProtocol1,MyProtocol2>

কারখানাটি রিটার্নের ধরণগুলি নির্দিষ্ট করে যেহেতু আমার প্রযুক্তিগতভাবে alচ্ছিক castালাই সম্পাদনের দরকার নেই? টাইপিং সম্পাদনের জন্য আমি কেবল সুইফটস ইনপিলিটেড টাইপিংয়ের উপর নির্ভর করতে পারি যেখানে আমি স্পষ্টভাবে প্রোটোকল ঘোষণা করি?
ড্যানিয়েল গালাস্কো

আপনি কী বলতে চাইছেন তা আমি বুঝতে পারছি না, আমার খারাপ ইংরেজি দক্ষতার জন্য দুঃখিত। যদি আপনি এটি সম্পর্কে বলছেন তবে -> UITableViewCell<MyProtocol>এটি অবৈধ, কারণ UITableViewCellজেনেরিক ধরণের নয়। আমি মনে করি এটি সংকলন করে না।
rintaro

আমি আপনার জেনেরিক প্রয়োগের কথা উল্লেখ করছি না বরং প্রয়োগের উদাহরণের উদাহরণ দিচ্ছি। যেখানে আপনি বলছেন যেহেতু প্রোটোকল = ...
ড্যানিয়েল গালাসকো

বা, আমি কেবল এটি করতে পেরেছিলাম: var সেল: প্রোটোকল <প্রোটোকল ওন, প্রোটোকল টু> = কিছুউইটিআইটিবেবল ভিউসেল হিসাবে এবং এক ভেরিয়েবলের উভয়ের সুবিধা পান
ড্যানিয়েল গালাসকো

4
আমি তাই মনে করি না. এমনকি যদি আপনি এটি করতে পারেন তবে cellকেবল প্রোটোকল পদ্ধতি রয়েছে (সংকলকের জন্য)।
rintaro

2

দুর্ভাগ্যক্রমে, সুইফট অবজেক্ট স্তরের প্রোটোকল কনফারেন্স সমর্থন করে না। যাইহোক, কিছুটা বিশ্রী কাজ রয়েছে যা আপনার উদ্দেশ্যে পরিবেশন করতে পারে।

struct VCWithSomeProtocol {
    let protocol: SomeProtocol
    let viewController: UIViewController

    init<T: UIViewController>(vc: T) where T: SomeProtocol {
        self.protocol = vc
        self.viewController = vc
    }
}

তারপরে, ইউভিউভিউ কনট্রোলারের যে কোনও কিছুতে আপনাকে যা করতে হবে, আপনি কাঠামোর। ভিউকন্ট্রোলার দিকটি এবং প্রোটোকলের দিকগুলির যে কোনও কিছুর প্রয়োজন হবে, আপনি প্রোটোকলটি উল্লেখ করতে পারবেন।

এই ক্ষেত্রে:

class SomeClass {
   let mySpecialViewController: VCWithSomeProtocol

   init<T: UIViewController>(injectedViewController: T) where T: SomeProtocol {
       self.mySpecialViewController = VCWithSomeProtocol(vc: injectedViewController)
   }
}

ইউআইভিউউকন্ট্রোলার সম্পর্কিত যে কোনও কিছু করার জন্য আপনার এখন মাইস্পেশিয়ালভিউ কনট্রোলারের প্রয়োজন হয়, আপনি কেবল মাইস্পেশিয়াল ভিউ কন্ট্রোলআরভিউ কনট্রোলারকে উল্লেখ করেন এবং যখনই আপনার কোনও প্রোটোকল ফাংশন করার প্রয়োজন হয়, আপনি মাইস্পেশালভিউকন্ট্রোলআরপ্রোটোকল রেফারেন্স করেন।

আশাকরি সুইফট 4 আমাদের ভবিষ্যতে এর সাথে সংযুক্ত প্রোটোকল সহ একটি বিষয় ঘোষণা করার অনুমতি দেবে। তবে আপাতত, এটি কাজ করে।

আশাকরি এটা সাহায্য করবে!


1

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

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

extension UITableCellView : ProtocolOne {}

// Or alternatively if you need to add a method, protocolMethod()
extension UITableCellView : ProcotolTwo {
   func protocolTwoMethod() -> String {
     return "Compliant method"
   }
}

ইতিমধ্যে রেফারেন্সযুক্ত সুইফ্ট ডকুমেন্টেশন ছাড়াও, নেট কুক্স নিবন্ধটি আরও উদাহরণগুলির সাথে বেমানান প্রকারের জেনেরিক ফাংশনগুলি দেখুন

এটি আমাদের বেস ধরণের বাস্তবায়ন এবং প্রোটোকলটিতে সংজ্ঞায়িত যুক্ত ইন্টারফেসের সাথে ডিল করতে সক্ষম হওয়ার নমনীয়তা দেয়।

আমি নিখোঁজ হতে পারে এমন আরও কিছুর উপায় আছে?

প্রোটোকল অ্যাডোপশন কেবল এটি করবে, একটি বস্তুকে প্রদত্ত প্রোটোকলকে মেনে চলবে। প্রতিকূল দিকটি সম্পর্কে সচেতন থাকুন, প্রদত্ত প্রোটোকল ধরণের একটি পরিবর্তনশীল প্রোটোকলের বাইরে কিছু জানেন না । তবে এটি এমন একটি প্রোটোকল সংজ্ঞায়িত করা যায় যাতে প্রয়োজনীয় সমস্ত পদ্ধতি / ভেরিয়েবল / ...

সরবরাহিত ধরণটি উল্লিখিত ইন্টারফেসের সাথে যথাযথভাবে সামঞ্জস্য না করে, কারখানাটি যে জিনিসটি দেয় তা হ'ল এবং তাই আমি বেস বর্গের ধরণ এবং ঘোষিত প্রোটোকল ইন্টারফেস উভয়ের সাথে যোগাযোগের ক্ষেত্রে নমনীয়তা চাই would

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


4
আমি যা বলছি তা নয় তবে ধন্যবাদ :) আমি কোনও শ্রেণীর এবং একটি নির্দিষ্ট প্রোটোকলের মাধ্যমে কোনও বস্তুর সাথে ইন্টারফেস করতে সক্ষম হতে চেয়েছিলাম। ঠিক কীভাবে আমি-সি-তে এনএসবজেক্ট <মাইপ্রোটোকল> আপত্তি = করতে পারি ... এটি দ্রুত বলা যায় না বলার অপেক্ষা রাখে না, আপনাকে অবজেক্টটিকে এর প্রোটোকলে ফেলে দিতে হবে
ড্যানিয়েল গালাসকো

0

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

উদাহরণ:

@objc protocol SomeInteractorInputProtocol {
    func getSomeString()
}

@objc protocol SomeInteractorOutputProtocol {
    optional func receiveSomeString(value:String)
}

@objc class SomeInteractor: NSObject, SomeInteractorInputProtocol {

    @IBOutlet var outputReceiver : AnyObject? = nil

    private var protocolOutputReceiver : SomeInteractorOutputProtocol? {
        get { return self.outputReceiver as? SomeInteractorOutputProtocol }
    }

    func getSomeString() {
        let aString = "This is some string."
        self.protocolOutputReceiver?.receiveSomeString?(aString)
    }
}

"আউটপুট রিসিভার "টিকে বেসরকারী" প্রোটোকল আউটপুট রিসিভার "হিসাবে optionচ্ছিক হিসাবে ঘোষণা করা হয়। পরেরটি (গণিত সম্পত্তি) এর মাধ্যমে সর্বদা আউটপুট রিসিভার (ওরফে প্রতিনিধি) অ্যাক্সেস করে আমি প্রোটোকলের সাথে সামঞ্জস্য না করে এমন কোনও বস্তু কার্যকরভাবে ফিল্টার করি। প্রোটোকলটি প্রয়োগ করে বা এমনকি বিদ্যমান কিনা তা আমি নিরাপদে ডেলিগেট অবজেক্টকে কল করতে simplyচ্ছিক চেইন ব্যবহার করতে পারি।

আপনার অবস্থার সাথে এটি প্রয়োগ করতে, আপনি পাবলিক আইভারটি "আপনারবেসক্লাস" টাইপ করতে পারেন? (যেকোনওবজেক্টের বিপরীতে), এবং প্রোটোকল কনফর্মেন্সটি প্রয়োগ করার জন্য ব্যক্তিগত গণিত সম্পত্তি ব্যবহার করুন। FWIW।

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