সুইফট-নির্দিষ্ট তথ্যের দুটি একেবারে অত্যন্ত গুরুত্বপূর্ণ টুকরো রয়েছে যা বিদ্যমান উত্তরগুলি থেকে অনুপস্থিত যা আমি মনে করি এটি সম্পূর্ণরূপে পরিষ্কার করতে সহায়তা করে।
- যদি কোনও প্রোটোকল কোনও প্রারম্ভিকটিকে প্রয়োজনীয় পদ্ধতি হিসাবে নির্দিষ্ট করে, তবে সেই প্রাথমিকটি সুইফ্টের
required
কীওয়ার্ড ব্যবহার করে চিহ্নিত করতে হবে ।
init
পদ্ধতিগুলির বিষয়ে সুইফ্টের উত্তরাধিকার সংক্রান্ত বিধিগুলির একটি বিশেষ সেট রয়েছে ।
TL; ড এই হল:
আপনি যদি কোনও আরম্ভকারীকে বাস্তবায়ন করেন তবে আপনি আর সুপারক্লাসের মনোনীত প্রারম্ভিকগুলির কোনওটির উত্তরাধিকারী হবেন না।
আপনার উত্তরাধিকারসূত্রে প্রাপ্ত একমাত্র প্রারম্ভিকরা হ'ল সুপার ক্লাস সুবিধাযুক্ত সূচনা যা কোনও পূর্বনির্ধারিত ইনিশিয়ালাইজারকে নির্দেশ করে যা আপনি ওভাররাইড করতে গিয়েছিলেন।
সুতরাং ... দীর্ঘ সংস্করণ জন্য প্রস্তুত?
init
পদ্ধতিগুলির বিষয়ে সুইফ্টের উত্তরাধিকার সংক্রান্ত বিধিগুলির একটি বিশেষ সেট রয়েছে ।
আমি জানি যে আমি তৈরি দুটি পয়েন্টের মধ্যে এটি ছিল দ্বিতীয়, তবে আমরা প্রথম পয়েন্টটি বুঝতে পারি না বা কেন এই required
শব্দটি এমনকি এই পয়েন্টটি না বোঝা পর্যন্ত উপস্থিত রয়েছে। একবার আমরা এই বিষয়টি বুঝতে পারলে, অন্যটি বেশ সুস্পষ্ট হয়ে যায়।
এই উত্তরের এই বিভাগে আমি যে সমস্ত তথ্য কভার করি তা হ'ল অ্যাপল এর ডকুমেন্টেশন থেকে পাওয়া গেছে ।
অ্যাপল ডক্স থেকে:
অবজেক্টিভ-সি-তে সাবক্লাসগুলির বিপরীতে, সুইফ্ট সাবক্লাসগুলি তাদের সুপারক্লাস প্রারম্ভিকগুলি ডিফল্টরূপে উত্তরাধিকার সূত্রে পায় না। সুইফ্টের দৃষ্টিভঙ্গি এমন পরিস্থিতিতে বাধা দেয় যেখানে সুপারক্লাস থেকে একটি সাধারণ সূচনাপ্রাপ্তর অধিকতর বিশেষায়িত সাবক্লাস দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত হয় এবং সাবক্লাসের একটি নতুন উদাহরণ তৈরি করতে ব্যবহৃত হয় যা পুরোপুরি বা সঠিকভাবে শুরু হয় না।
জোর আমার।
সুতরাং, সরাসরি সেখানে অ্যাপল ডক্স থেকে, আমরা দেখতে পাই যে সুইফ্ট সাবক্লাসগুলি সর্বদা তাদের সুপারক্লাসের init
পদ্ধতিগুলির উত্তরাধিকারী হয় না ।
সুতরাং, তারা কখন তাদের সুপারক্লাস থেকে উত্তরাধিকারী হবে?
দুটি নিয়ম রয়েছে যা সংজ্ঞায়িত হয় যখন একটি সাবক্লাস init
তার পিতামাতার কাছ থেকে পদ্ধতি উত্তরাধিকার সূত্রে প্রাপ্ত হয় । অ্যাপল ডক্স থেকে:
বিধি 1
যদি আপনার সাবক্লাস কোনও মনোনীত প্রারম্ভিক সংজ্ঞা দেয় না, এটি স্বয়ংক্রিয়ভাবে তার সমস্ত সুপারক্লাস মনোনীত প্রারম্ভিকদের উত্তরাধিকার সূত্রে প্রাপ্ত হয়।
বিধি 2
যদি আপনার সাবক্লাস তার সুপারক্লাস নির্ধারিত প্রাথমিক সকলের একটি বাস্তবায়ন সরবরাহ করে — হয় নিয়ম 1 অনুযায়ী উত্তরাধিকার সূত্রে বা তার সংজ্ঞা হিসাবে অংশ হিসাবে একটি কাস্টম বাস্তবায়ন সরবরাহ করে — তবে এটি স্বয়ংক্রিয়ভাবে সমস্ত সুপারক্লাস সুবিধার্থে প্রাথমিকভাবে উত্তরাধিকার সূত্রে প্রাপ্ত হয়।
রুল 2 কারণ এই কথোপকথনে বিশেষ করে প্রাসঙ্গিক নয় SKSpriteNode
'র init(coder: NSCoder)
একটি সুবিধার পদ্ধতি করার সম্ভাবনা কম।
সুতরাং, আপনার InfoBar
শ্রেণিটি required
আপনি যোগ করেছেন এমন পয়েন্ট অবধি প্রাথমিকভাবে উত্তরাধিকার সূত্রে আসছিল init(team: Team, size: CGSize)
।
তুমি ছিলে এই প্রদান করেন নি যদি init
পদ্ধতি এবং পরিবর্তে আপনার তৈরি InfoBar
's যোগ বৈশিষ্ট্য ঐচ্ছিক বা ডিফল্ট মান সঙ্গে তাদের প্রদান করা হয়, তাহলে আপনি এখনও inheriting হয়েছে চাই SKSpriteNode
' s init(coder: NSCoder)
। তবে, আমরা যখন নিজের নিজস্ব কাস্টম ইনিশিয়ালাইজার যুক্ত করেছি, তখন আমরা আমাদের সুপারক্লাসের মনোনীত প্রারম্ভিক (এবং সুবিধার প্রাথমিককরণ যা আমাদের প্রয়োগ করা আরম্ভকারীদের দিকে ইঙ্গিত দেয় না) উত্তরাধিকার সূত্রে উত্তোলন বন্ধ করে দিয়েছিলাম ।
সুতরাং, সরল উদাহরণ হিসাবে, আমি এটি উপস্থাপন করছি:
class Foo {
var foo: String
init(foo: String) {
self.foo = foo
}
}
class Bar: Foo {
var bar: String
init(foo: String, bar: String) {
self.bar = bar
super.init(foo: foo)
}
}
let x = Bar(foo: "Foo")
যা নিম্নলিখিত ত্রুটি উপস্থাপন করে:
কলটিতে প্যারামিটার 'বার' এর জন্য অনুপস্থিত তর্ক।
এটি যদি উদ্দেশ্য-সি হত তবে উত্তরাধিকার সূত্রে কোনও সমস্যা হবে না। যদি আমরা উদ্দেশ্য-সি-এর Bar
সাথে একটি সূচনা করি initWithFoo:
তবে self.bar
সম্পত্তিটি কেবল nil
। এটা সম্ভবত মহান নয়, কিন্তু এটি একটি পুরোপুরি এর বৈধ জন্য বস্তু হতে রাষ্ট্র। এটা না জন্য সুইফট বস্তু হতে একটি পুরোপুরি বৈধ রাষ্ট্র। self.bar
একটি ঐচ্ছিক নয় এবং হতে পারে না nil
।
আবার, আমরা আরম্ভকারীদের উত্তরাধিকারী হওয়ার একমাত্র উপায় হ'ল আমাদের নিজস্ব সরবরাহ না করা। সুতরাং আমরা যদি Bar
এর init(foo: String, bar: String)
মতো মুছে ফেলার মাধ্যমে উত্তরাধিকারের চেষ্টা করি :
class Bar: Foo {
var bar: String
}
এখন আমরা উত্তরাধিকারসূত্রে ফিরে এসেছি (সাজানোর ক্ষেত্রে) তবে এটি সংকলন করবে না ... এবং ত্রুটি বার্তাটি ঠিক কীভাবে আমরা সুপারক্লাস init
পদ্ধতির উত্তরাধিকারী না তা ব্যাখ্যা করে:
সমস্যা: ক্লাস 'বার' এর কোনও আরম্ভকারী নেই
ফিক্স-ইট: স্টোরড প্রপার্টি 'বার' ইনিশিয়ালাইজার ছাড়াই সংশ্লেষিত আরম্ভকারীদের বাধা দেয়
আমরা যদি আমাদের সাবক্লাসে সঞ্চিত বৈশিষ্ট্যগুলি যুক্ত করে রেখেছি তবে সুপারক্লাস ইনিশিয়ালাইজারগুলির সাথে আমাদের সাবক্লাসের একটি বৈধ উদাহরণ তৈরি করার কোনও সুইফট উপায় নেই যা সম্ভবত আমাদের সাবক্লাসের সঞ্চিত বৈশিষ্ট্যগুলি সম্পর্কে জানতে পারে না।
ঠিক আছে, ঠিক আছে, কেন আমাকে কিছুটা প্রয়োগ init(coder: NSCoder)
করতে হবে? এটা কেন required
?
সুইফটের init
পদ্ধতিগুলি উত্তরাধিকারের নিয়মের একটি বিশেষ সেট দ্বারা চালিত হতে পারে, তবে প্রোটোকল কনফর্মেন্সটি এখনও শৃঙ্খলাবদ্ধভাবে উত্তরাধিকার সূত্রে প্রাপ্ত। যদি কোনও পিতামাতা শ্রেণি কোনও প্রোটোকলে সম্মতি দেয় তবে এর সাবক্লাসগুলি অবশ্যই সেই প্রোটোকলের সাথে সঙ্গতিপূর্ণ হবে।
সাধারণত, এটি কোনও সমস্যা নয়, কারণ বেশিরভাগ প্রোটোকলগুলিতে কেবল এমন পদ্ধতিগুলির প্রয়োজন হয় যা সুইফটে বিশেষ উত্তরাধিকারের নিয়ম অনুসারে খেলা হয় না, তাই আপনি যদি প্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন কোনও শ্রেণীর কাছ থেকে উত্তরাধিকারী হন তবে আপনি সমস্তটি উত্তরাধিকার সূত্রে প্রাপ্ত হন এমন পদ্ধতি বা বৈশিষ্ট্য যা ক্লাসকে প্রোটোকল কনফারেন্সটি পূরণ করতে দেয়।
তবে মনে রাখবেন, সুইফটের init
পদ্ধতিগুলি একটি বিশেষ নিয়মের দ্বারা খেলে এবং সর্বদা উত্তরাধিকারসূত্রে হয় না। এর কারণে, এমন একটি শ্রেণি যা একটি প্রোটোকলের সাথে সামঞ্জস্য করে যার জন্য বিশেষ init
পদ্ধতিগুলির প্রয়োজন (যেমন NSCoding
) প্রয়োজন বর্গটি সেই init
পদ্ধতিগুলি চিহ্নিত করে required
।
এই উদাহরণ বিবেচনা করুন:
protocol InitProtocol {
init(foo: Int)
}
class ConformingClass: InitProtocol {
var foo: Int
init(foo: Int) {
self.foo = foo
}
}
এটি সংকলন করে না। এটি নিম্নলিখিত সতর্কতা উত্পন্ন করে:
ইস্যু: ইনিশিয়ালাইজারের প্রয়োজনীয়তা 'থিম (ফু :)' কেবলমাত্র চূড়ান্ত শ্রেণীর 'কনফর্মিংক্লাস' এর 'প্রয়োজনীয়' প্রারম্ভক দ্বারা সন্তুষ্ট হতে পারে
ফিক্স-এটি: সন্নিবেশ প্রয়োজন
এটি আমার কাছে init(foo: Int)
প্রারম্ভিক প্রয়োজনীয়টি তৈরি করতে চায় । আমি ক্লাস করেও এটি খুশি করতে পারি final
(যার অর্থ শ্রেণি উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে না)।
তো, আমি সাবক্লাস করলে কী হয়? এই জায়গা থেকে, আমি সাবক্লাস, আমি ভাল আছি। আমি যদি কোনও প্রাথমিককরণ যুক্ত করি তবে হঠাৎ আমার আর উত্তরাধিকারসূত্রে নেই init(foo:)
। এটি সমস্যাযুক্ত কারণ এখন আমি আর মেনে চলছি না InitProtocol
। প্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন ক্লাস থেকে আমি সাবক্লাস করতে পারি না এবং তারপরে হঠাৎ করে সিদ্ধান্ত নিতে পারি আমি আর সেই প্রোটোকলের সাথে সামঞ্জস্য রাখতে চাই না। আমি প্রোটোকল কনফর্মেন্স উত্তরাধিকার সূত্রে পেয়েছি, কিন্তু সুইফট init
পদ্ধতিটির উত্তরাধিকারের সাথে যেভাবে কাজ করে, সেই প্রোটোকলের সাথে খাপ খাইয়ে নিতে প্রয়োজনীয় কিছুর অংশ আমি উত্তরাধিকার সূত্রে পাই নি এবং তা অবশ্যই বাস্তবায়ন করতে হবে।
ঠিক আছে, এই সব বোঝার। তবে কেন আমি আরও সহায়ক ত্রুটি বার্তা পেতে পারি না?
যুক্তিযুক্তভাবে, ত্রুটি বার্তাটি আরও স্পষ্ট বা আরও ভাল হতে পারে যদি এটি নির্দিষ্ট করে যে আপনার শ্রেণি আর উত্তরাধিকার সূত্রে প্রাপ্ত NSCoding
প্রোটোকলের সাথে মেনে চলেছে না এবং এটি কার্যকর করার জন্য আপনাকে প্রয়োগ করতে হবে init(coder: NSCoder)
। অবশ্যই।
তবে এক্সকোড সহজেই এই বার্তাটি তৈরি করতে পারে না কারণ এটি প্রয়োজনীয় পদ্ধতি প্রয়োগ বা উত্তরাধিকারসূত্রে প্রাপ্ত না হওয়ায় প্রকৃতপক্ষে সর্বদা আসল সমস্যা হবে না। প্রোটোকল কনফরমেশন ছাড়াও init
পদ্ধতিগুলি তৈরি করার অন্য একটি কারণ রয়েছে required
এবং এটি কারখানা পদ্ধতি।
আমি যদি সঠিক কারখানার পদ্ধতি লিখতে চাই তবে আমাকে রিটার্নের ধরণটি উল্লেখ করতে হবে Self
(অবজেক্টিভ সি এর সমতুল্য সুইফ্টের সমতুল্য instanceType
)। তবে এটি করার জন্য, আমার আসলে একটি required
প্রাথমিক পদ্ধতি ব্যবহার করা দরকার method
class Box {
var size: CGSize
init(size: CGSize) {
self.size = size
}
class func factory() -> Self {
return self.init(size: CGSizeZero)
}
}
এটি ত্রুটি উত্পন্ন করে:
মেটাটাইপ মান সহ শ্রেণি টাইপ 'সেলফ' এর একটি অবজেক্ট তৈরি করা অবশ্যই একটি 'প্রয়োজনীয়' আরম্ভকারী ব্যবহার করা উচিত
এটি মূলত একই সমস্যা। যদি আমরা সাবক্লাস করি তবে Box
আমাদের সাবক্লাসগুলি শ্রেণি পদ্ধতিতে উত্তরাধিকারী হবে factory
। সুতরাং আমরা কল করতে পারে SubclassedBox.factory()
। তবে, পদ্ধতির required
কীওয়ার্ড ব্যতীত init(size:)
, Box
সাবক্লাসগুলি self.init(size:)
যে factory
কল করছে তার উত্তরাধিকারী হওয়ার নিশ্চয়তা নেই ।
সুতরাং আমরা অবশ্যই এই পদ্ধতিটি তৈরি করতে হবে required
যদি আমরা এই জাতীয় কারখানার পদ্ধতি চাই, এবং এর অর্থ আমাদের ক্লাস যদি এই পদ্ধতিটি প্রয়োগ করে, তবে আমাদের কাছে একটি required
ইনিশিয়ালার পদ্ধতি থাকবে এবং আমরা এখানে ঠিক একই সমস্যার মধ্যে চলে যাব you've NSCoding
প্রোটোকল সহ
শেষ পর্যন্ত, এগুলি সমস্ত বুনিয়াদি বোঝায় যে সুইফ্টের আরম্ভকারীরা উত্তরাধিকার নিয়মের সামান্য ভিন্ন সেট দ্বারা খেলেন যার অর্থ আপনি আপনার সুপারক্লাস থেকে আরম্ভকারীদের উত্তরাধিকারী হওয়ার গ্যারান্টিযুক্ত নন। এটি হ'ল কারণ সুপার ক্লাস ইনিশিয়ালাইজারগুলি আপনার নতুন সঞ্চিত বৈশিষ্ট্যগুলি সম্পর্কে জানতে পারে না এবং তারা আপনার অবজেক্টটিকে বৈধ অবস্থায় রূপান্তর করতে পারে না। কিন্তু, বিভিন্ন কারণে, একটি সুপারক্লাস হিসাবে একটি ইনিশিয়ালাইজার হিসাবে চিহ্নিত করতে পারে required
। যখন এটি হয়, আমরা হয় খুব নির্দিষ্ট পরিস্থিতিতে একটি নিয়োগ করতে পারি যার মাধ্যমে আমরা আসলে required
পদ্ধতিটি উত্তরাধিকার সূত্রে পাই, বা আমাদের অবশ্যই এটি প্রয়োগ করতে হবে।
এখানে মূল বক্তব্যটি হ'ল আমরা যদি এখানে ত্রুটিটি দেখতে পাচ্ছি তবে এর অর্থ হ'ল আপনার শ্রেণি আসলে পদ্ধতিটি মোটেও বাস্তবায়ন করছে না।
সম্ভবত সুইফ্ট সাবক্লাসগুলি সর্বদা তাদের পিতামাতার init
পদ্ধতিগুলির উত্তরাধিকারী হয় না (এই সমস্যাটি পুরোপুরি বোঝার জন্য একেবারে কেন্দ্রিক বলে আমি মনে করি) এই ড্রিলের পক্ষে সম্ভবত একটি চূড়ান্ত উদাহরণ , এই উদাহরণটি বিবেচনা করুন:
class Foo {
init(a: Int, b: Int, c: Int) {
// do nothing
}
}
class Bar: Foo {
init(string: String) {
super.init(a: 0, b: 1, c: 2)
// do more nothing
}
}
let f = Foo(a: 0, b: 1, c: 2)
let b = Bar(a: 0, b: 1, c: 2)
এটি সংকলন করতে ব্যর্থ।
এটি প্রদত্ত ত্রুটি বার্তাটি কিছুটা বিভ্রান্তিকর:
কলটিতে অতিরিক্ত আর্গুমেন্ট 'বি'
কিন্তু বিন্দু, তাই Bar
কোন উত্তরাধিকারী না Foo
এর init
পদ্ধতি কারণ এটি দুই বিশেষ ক্ষেত্রে উভয় inheriting জন্য সন্তুষ্ট করেননি init
তার পিতা বা মাতা ক্লাস থেকে পদ্ধতি।
যদি এটি অবজেক্টিভ-সি থাকত তবে আমরা init
কোনও সমস্যা ছাড়াই উত্তরাধিকার সূত্রে চাই , কারণ উদ্দেশ্য-সি বস্তুর বৈশিষ্ট্যগুলি আরম্ভ না করে পুরোপুরি খুশি (যদিও একজন বিকাশকারী হিসাবে আপনি এতে খুশি হননি)। সুইফটে, এটি সহজভাবে করবে না। আপনার কোনও অবৈধ অবস্থা থাকতে পারে না এবং উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণীর সূচনা কেবল অবৈধ অবজেক্টের স্থিতিতে ডেকে আনতে পারে।
init(collection:MPMediaItemCollection)
। আপনাকে অবশ্যই একটি বাস্তব মিডিয়া আইটেম সংগ্রহ সরবরাহ করতে হবে; এটি এই শ্রেণীর পয়েন্ট। এই শ্রেণিটি কেবল একটি ছাড়া তাত্ক্ষণিকভাবে চলতে পারে। এটি সংগ্রহটি বিশ্লেষণ করতে এবং এক ডজন উদাহরণ ভেরিয়েবল সূচনা করতে চলেছে। এটি হ'ল এটির একমাত্র এবং একমাত্র মনোনীত প্রারম্ভিকের পুরো বিষয়টি! সুতরাং,init(coder:)
এখানে সরবরাহের কোনও অর্থবহ (বা এমনকি অর্থহীন) এমপিএমডিআইটিম সংগ্রহ নেই; শুধুমাত্রfatalError
পদ্ধতির সঠিক।