শ্রেণি তার সুপারক্লাসের প্রয়োজনীয় সদস্যদের বাস্তবায়ন করে না


155

তাই আমি আজই এক্সকোড 6 বিটা 5 এ আপডেট হয়েছি এবং লক্ষ্য করেছি যে অ্যাপলের ক্লাসগুলির প্রায় আমার সমস্ত সাবক্লাসে আমি ত্রুটি পেয়েছি।

ত্রুটিটি বলে:

ক্লাস 'x' এর সুপারক্লাসের প্রয়োজনীয় সদস্যদের প্রয়োগ করে না

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

class InfoBar: SKSpriteNode  { //Error message here

    let team: Team
    let healthBar: SKSpriteNode

    init(team: Team, size: CGSize) {
        self.team = team
        if self.team == Team.TeamGood {
            healthBar = SKSpriteNode(color: UIColor.greenColor(), size:size)
        }
        else {
            healthBar = SKSpriteNode(color: UIColor.redColor(), size:size)
        }
        super.init(texture:nil, color: UIColor.darkGrayColor(), size: size)

        self.addChild(healthBar)

    }

}

সুতরাং আমার প্রশ্ন হ'ল কেন আমি এই ত্রুটিটি পাচ্ছি, এবং আমি কীভাবে এটি সংশোধন করতে পারি? আমি কী তা বাস্তবায়ন করছি না? আমি একটি মনোনীত প্রারম্ভিক কল করছি।

উত্তর:


127

বিকাশকারী ফোরামে কোনও অ্যাপল কর্মচারীর কাছ থেকে:

"আপনি সত্যই এনএসকোডিং-সামঞ্জস্যপূর্ণ হতে চান না এমন সংকলক এবং বিল্ট প্রোগ্রামকে ঘোষণা করার একটি উপায় হ'ল এরকম কিছু করা:"

required init(coder: NSCoder) {
  fatalError("NSCoding not supported")
}

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


আপনি যে বিকল্পটি আরও ভালভাবে কাজ করতে পারেন তা হ'ল পদ্ধতিটি সুবিধামত উদ্যোগ হিসাবে প্রয়োগ করা, যেমন:

convenience required init(coder: NSCoder) {
    self.init(stringParam: "", intParam: 5)
}

একটি প্রারম্ভিককে কলটি নোট করুন self। মারাত্মক ত্রুটি ছোঁড়া এড়াতে, আপনাকে সমস্ত অ-alচ্ছিক বৈশিষ্ট্যের বিপরীতে প্যারামিটারগুলির জন্য কেবল ডামি মানগুলি ব্যবহার করতে দেয়।


তৃতীয় বিকল্পটি হ'ল সুপারকে কল করার সময় পদ্ধতিটি কার্যকর করা এবং আপনার সমস্ত অ-optionচ্ছিক বৈশিষ্ট্য আরম্ভ করা। কোনও স্টোরিবোর্ড থেকে বস্তুটি বোঝা হচ্ছে এমন দৃশ্য হলে আপনার এই পন্থাটি গ্রহণ করা উচিত:

required init(coder aDecoder: NSCoder!) {
    foo = "some string"
    bar = 9001

    super.init(coder: aDecoder)
}

3
যদিও দ্বিতীয় বিকল্পটি বেশিরভাগ বাস্তব জীবনের ক্ষেত্রে অকেজো। উদাহরণস্বরূপ, আমার প্রয়োজনীয় ইনিশিয়ালাইজারটি ধরুন init(collection:MPMediaItemCollection)। আপনাকে অবশ্যই একটি বাস্তব মিডিয়া আইটেম সংগ্রহ সরবরাহ করতে হবে; এটি এই শ্রেণীর পয়েন্ট। এই শ্রেণিটি কেবল একটি ছাড়া তাত্ক্ষণিকভাবে চলতে পারে। এটি সংগ্রহটি বিশ্লেষণ করতে এবং এক ডজন উদাহরণ ভেরিয়েবল সূচনা করতে চলেছে। এটি হ'ল এটির একমাত্র এবং একমাত্র মনোনীত প্রারম্ভিকের পুরো বিষয়টি! সুতরাং, init(coder:)এখানে সরবরাহের কোনও অর্থবহ (বা এমনকি অর্থহীন) এমপিএমডিআইটিম সংগ্রহ নেই; শুধুমাত্র fatalErrorপদ্ধতির সঠিক।
ম্যাট

@ ম্যাট সঠিক, এক বা অন্য বিকল্পটি বিভিন্ন পরিস্থিতিতে আরও ভাল কাজ করবে।
বেন কেন

ঠিক আছে, এবং আমি দ্বিতীয় বিকল্পটি স্বতন্ত্রভাবে আবিষ্কার করেছি এবং বিবেচনা করেছি এবং কখনও কখনও এটি উপলব্ধি করতে পারে। উদাহরণস্বরূপ আমি আমার ডিআই ঘোষণা করতে পারতাম init(collection:MPMediaItemCollection!)। যে init(coder:)শূন্য পাস করতে অনুমতি দেবে । তবে আমি বুঝতে পেরেছিলাম: না, এখন আপনি কেবল সংকলককে বোকা বানাচ্ছেন। নীল পাস করা গ্রহণযোগ্য নয়, তাই ফেলে দিন fatalErrorএবং এগিয়ে যান। :)
ম্যাট

1
আমি জানি এই প্রশ্নটি এবং এর উত্তরগুলি এখন একধরনের পুরানো, তবে আমি একটি নতুন উত্তর পোস্ট করেছি যা এমন কিছু পয়েন্টগুলিকে সম্বোধন করে যা আমি মনে করি যে এই ত্রুটিটি আসলে বিদ্যমান উত্তরগুলির দ্বারা সমাধান করা হয়নি যা বুঝতে সমস্যা হয়।
nhgrif

ভাল উত্তর. আমি আপনার সাথে একমত যে সুইফট সবসময় সুপার ইনিশিয়ালাইজারদের উত্তরাধিকার সূত্রে হয় না এই বোঝার জন্য প্রয়োজনীয় pattern
বেন কেন

71

সুইফট-নির্দিষ্ট তথ্যের দুটি একেবারে অত্যন্ত গুরুত্বপূর্ণ টুকরো রয়েছে যা বিদ্যমান উত্তরগুলি থেকে অনুপস্থিত যা আমি মনে করি এটি সম্পূর্ণরূপে পরিষ্কার করতে সহায়তা করে।

  1. যদি কোনও প্রোটোকল কোনও প্রারম্ভিকটিকে প্রয়োজনীয় পদ্ধতি হিসাবে নির্দিষ্ট করে, তবে সেই প্রাথমিকটি সুইফ্টের requiredকীওয়ার্ড ব্যবহার করে চিহ্নিত করতে হবে ।
  2. 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কোনও সমস্যা ছাড়াই উত্তরাধিকার সূত্রে চাই , কারণ উদ্দেশ্য-সি বস্তুর বৈশিষ্ট্যগুলি আরম্ভ না করে পুরোপুরি খুশি (যদিও একজন বিকাশকারী হিসাবে আপনি এতে খুশি হননি)। সুইফটে, এটি সহজভাবে করবে না। আপনার কোনও অবৈধ অবস্থা থাকতে পারে না এবং উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণীর সূচনা কেবল অবৈধ অবজেক্টের স্থিতিতে ডেকে আনতে পারে।


আপনি এই বাক্যটির অর্থ কী ব্যাখ্যা করতে পারেন বা একটি উদাহরণ দিতে পারেন? "(এবং সুবিধামত প্রাথমিককরণ যা আমরা প্রয়োগকারী প্রারম্ভিকদের দিকে নির্দেশ করে না)"
অ্যাবে জ্যাকসন

জমকালো উত্তর! আমি আরও এস পোস্টগুলি কেবল কীভাবে পরিবর্তিত হবে তার চেয়ে কেন এটির মতো হওয়া চাই ।
আলেকজান্ডার ভ্যাসেনিন

56

কেন এই সমস্যা দেখা দিয়েছে? ঠিক আছে, সরল সত্যটি এটি সর্বদা ছিল যে আপনার ক্লাস পরিচালনা করতে প্রস্তুত নয় এমন প্রারম্ভিকদের সাথে কাজ করার জন্য ম্যাক ওএস এক্স 10.0-এ কোকো ফিরে প্রোগ্রামিং শুরু করার পর থেকেই গুরুত্বপূর্ণ ছিল (অর্থাত্-সি-তে)এই ক্ষেত্রে আপনার দায়িত্ব সম্পর্কে ডক্স সর্বদা পরিষ্কার ছিল। কিন্তু আমাদের মধ্যে কতজন তাদের সম্পূর্ণরূপে এবং চিঠিটি পূরণ করতে বিরক্ত করেছিল? সম্ভবত আমাদের কেউই না! এবং সংকলক তাদের প্রয়োগ করে না; এটি সমস্ত নিখুঁত প্রচলিত ছিল।

উদাহরণস্বরূপ, আমার মনোনীত ইনিশিয়ালাইজার সহ আমার উদ্দেশ্য-সি ভিউ কন্ট্রোলার সাবক্লাসে:

- (instancetype) initWithCollection: (MPMediaItemCollection*) coll;

... এটি আমাদের পক্ষে সত্যিকারের একটি মিডিয়া আইটেম সংগ্রহ করা অত্যন্ত গুরুত্বপূর্ণ: উদাহরণটি কেবলমাত্র একটি ছাড়া অস্তিত্বের মধ্যে আসতে পারে না। তবে আমি কাউকে initপরিবর্তে খালি-হাড় দিয়ে আমাকে আরম্ভ করতে বাধা দিতে কোনও "স্টপার" লিখেছি না । আমার একটি লেখা উচিত ছিল (প্রকৃতপক্ষে, যথাযথভাবে বলতে গেলে, আমার initWithNibName:bundle:উত্তরাধিকারসূত্রে মনোনীত আরম্ভকারী হিসাবে একটি প্রয়োগ লেখা উচিত ছিল ); তবে আমি বিরক্ত করতে খুব অলস ছিলাম, কারণ আমি "জানতাম" আমি ভুলভাবে নিজের ক্লাসটি সেভাবে আরম্ভ করব না। এটি একটি ফাঁক গর্ত ছেড়ে গেছে। অবজেক্টিভ-সি-তে, কেউ আমার আইভারকে অবিচ্ছিন্ন রেখে খালি-হাড়ের ডাক দিতে পারেinit এবং আমরা কোনও প্যাডেল ছাড়াই খাঁড়ি পর্যন্ত আছি।

দ্রুত, আশ্চর্যজনকভাবে, বেশিরভাগ ক্ষেত্রে আমাকে নিজেকে থেকে বাঁচায়। এই অ্যাপটি সুইফটে অনুবাদ করার সাথে সাথে পুরো সমস্যাটি চলে গেল। সুইফট কার্যকরভাবে আমার জন্য স্টপার তৈরি করে! যদি init(collection:MPMediaItemCollection)আমার ক্লাসে ঘোষণা করা একমাত্র মনোনীত আরম্ভকারী হয় তবে খালি-হাড় ডেকে আমাকে আরম্ভ করা যাবে না init()। এটি একটি অলৌকিক ঘটনা!

5 তম বংশের মধ্যে যা ঘটেছিল তা কেবল এটিই যে সংকলকটি বুঝতে পেরেছে যে অলৌকিক ঘটনাটি কাজ করে না init(coder:), কারণ তাত্ত্বিকভাবে এই শ্রেণীর উদাহরণটি কোনও নিব থেকে আসতে পারে, এবং সংকলক সেটি প্রতিরোধ করতে পারে না - এবং যখন নিব বোঝা, init(coder:)ডাকা হবে। সুতরাং সংকলক আপনাকে স্পপারটি স্পষ্টভাবে লিখতে বাধ্য করে। এবং বেশ ঠিক।


এই জাতীয় বিস্তারিত উত্তরের জন্য ধন্যবাদ। এটি সত্যই বিষয়টি নিয়ে আলোকপাত করে।
জুলিয়ান ওসোরিও

কীভাবে কম্পাইলারটি শাট আপ করতে হবে তা বলার জন্য পাস্তা 12 -এর জন্য একটি উত্সাহ, তবে এটি আপনাকে প্রথম স্থানটিতে কীভাবে জ্বলজ্বল করছে তাতে আমাকে আঁকড়ে ধরার জন্য আপনার কাছেও একটি উত্সাহ।
গ্যারেট অ্যালব্রাইট

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

5
@DanGreenfield না, এটা তুমি কি কিছু আরম্ভ করতে, কারণ আপনি কখনই একে ডাকতে আপনি শুধু রাখা চলুন জোর করেন না fatalErrorছিপি বর্ণিত stackoverflow.com/a/25128815/341994 । এটি কেবল একটি ব্যবহারকারী কোড স্নিপেট তৈরি করুন এবং এখন থেকে আপনি এটি যেখানে প্রয়োজন সেখানে এটি ঠিকঠাক করতে পারেন। আধ সেকেন্ড সময় নেয়।
ম্যাট

1
@ এনজিগ্রিফ, ভাল কথা, প্রশ্নটি পুরো ব্যাক গল্পের জন্য জিজ্ঞাসা করে নি। এই জ্যাম থেকে বেরিয়ে কীভাবে এগিয়ে যাওয়া যায় তা কেবল ছিল। সম্পূর্ণ গল্পটি আমার বইতে দেওয়া হয়েছে: apeth.com/swiftBook/ch04.html#_class_initializer
ম্যাট

33

যোগ

required init(coder aDecoder: NSCoder!) {
  super.init(coder: aDecoder)
}

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

1
হা! আমি এটি একটি বাগ হতে পারে বলার সাথে সাথে বুঝতে পারলাম, এটি আসলে যৌক্তিক ধারণা দেয়। আমি সম্মত হ'ল এটি প্রচুর নষ্ট কোড হবে, যেহেতু আপনার মতো আমি এই আরম্ভ পদ্ধতিটি কখনও ব্যবহার করব না। এখনও একটি মার্জিত সমাধান সম্পর্কে নিশ্চিত না
গগন সিং

2
আমারো একই ইস্যু ছিল. এটি "প্রয়োজনীয় থিম" দিয়ে বোঝা যায়, তবে আমি যে প্রত্যাশা করেছি তা দ্রুতই সহজ নয়। এই সমস্ত "alচ্ছিক" ভাষা প্রয়োজনের তুলনায় আরও জটিল করে তুলছে। এবং ডিএসএল এবং এওপি-র জন্য কোনও সমর্থন নেই। আমি আরও হতাশ হচ্ছি।
ব্যবহারকারী 810395

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

5
আমি মনে করি তাদের অর্থ হ'ল আপনি নিজের কোনও প্রারম্ভকালীন ঘোষণা না করে প্রয়োজনীয় প্রারম্ভিককে সন্তুষ্ট করতে পারবেন, যার ফলস্বরূপ সমস্ত আদ্যক্ষর উত্তরাধিকার সূত্রে প্রাপ্ত হবে।
এপিক বাইট 4'14
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.