সুইফ্ট ইনিশিয়েলাইজাররা কেন তাদের সুপারক্লাসে সুবিধা ইনিশিয়ালাইজারদের কল করতে পারে না?


88

দুটি শ্রেণি বিবেচনা করুন:

class A {
    var x: Int

    init(x: Int) {
        self.x = x
    }

    convenience init() {
        self.init(x: 0)
    }
}

class B: A {
    init() {
        super.init() // Error: Must call a designated initializer of the superclass 'A'
    }
}

কেন এটি অনুমোদিত নয় তা আমি দেখতে পাচ্ছি না। পরিশেষে, প্রতিটি ক্লাস মনোনীত সূচনাকারী কোনো মান তাদের প্রয়োজনীয় সঙ্গে বলা হয়, তবে কেন আমি নিজেকে পুনরাবৃত্তি করতে হবে B's initজন্য ডিফল্ট মান নির্দিষ্ট করে xআবার, যখন সুবিধা initমধ্যে Aশুধু জরিমানা করবেন?


4
আমি একটি উত্তর অনুসন্ধান করেছি কিন্তু আমি সন্তুষ্ট করতে পারে এমন কোনও পাই না। এটি সম্ভবত কিছু বাস্তবায়নের কারণ। সুবিধার প্রাথমিকের জন্য অনুসন্ধানের চেয়ে অন্য শ্রেণিতে মনোনীত ইনিশিয়ালাইজারগুলির সন্ধান করা ... বা এর মতো কিছু হতে পারে।
সুলতান

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

উত্তর:


24

এটি সুইফ্ট প্রোগ্রামিং গাইডে উল্লিখিত "ইনিশিয়ালার চেইনিং" বিধিগুলির নিয়ম 1, যা এই লিখিত রয়েছে:

বিধি 1: মনোনীত ইনিশিয়ালাইজারদের অবশ্যই তাদের তাত্ক্ষণিক সুপারক্লাস থেকে একটি মনোনীত প্রাথমিক কল করতে হবে।

https://developer.apple.com/library/content/docamentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html

জোর আমার। মনোনীত ইনিশিয়ালাইজার সুবিধামত আরম্ভকারীদের কল করতে পারে না।

একটি ডায়াগ্রাম রয়েছে যা প্রারম্ভক "নির্দেশাবলী" অনুমোদিত তা প্রমাণ করার জন্য নিয়মের সাথে চলে:

ইনিশিয়ালাইজার চেইনিং


80
তবে কেন এভাবে করা হয়? ডকুমেন্টেশনটি কেবলমাত্র বলে যে এটি নকশাটি সহজতর করে, তবে আমি যদি দেখি না যে এই ক্ষেত্রে কী হয় তবে আমি যদি নিয়মিত ডিজিটাল মানগুলিতে নিয়মিতভাবে ডিফল্ট মানগুলি নির্দিষ্ট করে নিজেকে পুনরাবৃত্তি করতেই থাকি তবে বেশিরভাগ ক্ষেত্রেই যখন সুবিধায় থাকা ডিফল্ট মানগুলি আমি যত্নবান না করি ইনিশিয়ালাররা কি করবে?
রবার্ট

4
সুবিধামত প্রাথমিকদের কল করতে সক্ষম হতে বলার জন্য আমি এই প্রশ্নের কয়েক দিন পরে 17266917 একটি বাগ দায়ের করেছি। এখনও কোনও প্রতিক্রিয়া জানেনি, তবে আমার অন্য সুইফট বাগের রিপোর্টগুলির জন্য আমার কোনওও নেই!
রবার্ট

8
আশা করি তারা সুবিধামত প্রাথমিকদের কল করার অনুমতি দেবে। এসডিকে কিছু শ্রেণির জন্য একটি নির্দিষ্ট আচরণ অর্জনের অন্য কোনও উপায় নেই তবে সুবিধাকে প্রাথমিককরণ বলা calling দেখুন SCNGeometry: আপনি SCNGeometryElementকেবল সুবিধার্থ সূচকটি ব্যবহার করেই এস যুক্ত করতে পারেন , সুতরাং কেউ এ থেকে উত্তরাধিকারী হতে পারে না।
Spak

4
এটি খুব দরিদ্র ভাষার নকশার সিদ্ধান্ত। আমার নতুন অ্যাপ্লিকেশনটির শুরু থেকেই আমি সিদ্ধান্ত নিয়েছিলাম দ্রুতগতির সাথে বিকাশ করার জন্য আমাকে আমার সাবক্লাস থেকে এনএসউইনড্রো কন্ট্রোলআরিনাইট (উইন্ডোনিবনেম) কল করতে হবে, এবং আমি কেবল এটি করতে পারি না :(
ইউনিকাস

4
@ কাইসারলুদি: দরকারী কিছুই নয়, নিম্নলিখিত প্রতিক্রিয়া দিয়ে এটি বন্ধ করা হয়েছিল: "এটি ডিজাইনের মাধ্যমে এবং কোনও প্রাসঙ্গিক বাগ এই অঞ্চলে সাজানো হয়েছে।"
রবার্ট

21

বিবেচনা

class A
{
    var a: Int
    var b: Int

    init (a: Int, b: Int) {
        print("Entering A.init(a,b)")
        self.a = a; self.b = b
    }

    convenience init(a: Int) {
        print("Entering A.init(a)")
        self.init(a: a, b: 0)
    }

    convenience init() {
        print("Entering A.init()")
        self.init(a:0)
    }
}


class B : A
{
    var c: Int

    override init(a: Int, b: Int)
    {
        print("Entering B.init(a,b)")
        self.c = 0; super.init(a: a, b: b)
    }
}

var b = B()

যেহেতু এ ক্লাসের সমস্ত মনোনীত প্রারম্ভিককে ওভাররাইড করা হয়েছে, ক্লাস বি এ এর ​​সমস্ত সুবিধাযুক্ত প্রারম্ভিকদের উত্তরাধিকারী হবে

Entering A.init()
Entering A.init(a:)
Entering B.init(a:,b:)
Entering A.init(a:,b:)

এখন, যদি মনোনীত ইনিশিয়ালাইজার বি.এন.ইইটি (ক: বি :) কে বেস ক্লাসের সুবিধামত ইনিশিয়ালাইজার A.init (a :) কল করার অনুমতি দেওয়া হত, এর ফলে B.init (a:, b:) এ পুনরাবৃত্তি কল আসতে পারে )।


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

@ ফ্লুইডসোনিক তবে এটি উন্মাদ হবে কারণ আপনার কাঠামো এবং শ্রেণি পদ্ধতিগুলি কীভাবে ব্যবহৃত হয়েছিল তার উপর নির্ভর করে পরিবর্তিত হবে। ডিবাগিং মজা কল্পনা করুন!
kdazzle

4
@kdazzle না ক্লাসের কাঠামো বা শ্রেণীর পদ্ধতিগুলি পরিবর্তন হবে না। তাদের কেন করা উচিত? - আমি কেবলমাত্র সমস্যাটিই ভাবতে পারি যে সুবিধামুখী সূচনাপ্রাপ্তরা অবশ্যই একটি সাবক্লাসের মনোনীত প্রারম্ভিকের কাছে উত্তরাধিকারসূত্রে এবং স্থায়ীভাবে তার নিজের শ্রেণীর মনোনীত প্রারম্ভিককে যখন উত্তরাধিকার সূত্রে প্রাপ্ত হয় না তবে সাবক্লাস থেকে প্রেরণ করা হয় ততক্ষণ করতে হবে।
ফ্লুইডসোনিক

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

13

এটি কারণ আপনি অসীম পুনরাবৃত্তি দিয়ে শেষ করতে পারেন। বিবেচনা:

class SuperClass {
    init() {
    }

    convenience init(value: Int) {
        // calls init() of the current class
        // so init() for SubClass if the instance
        // is a SubClass
        self.init()
    }
}

class SubClass : SuperClass {
    override init() {
        super.init(value: 10)
    }
}

এবং তাকান:

let a = SubClass()

যা ডাকবে SubClass.init() যা কল SuperClass.init(value:)করবে SubClass.init()

মনোনীত / সুবিধাপ্রাপ্তির নিয়মগুলি এমনভাবে নকশা করা হয়েছে যে কোনও শ্রেণি সূচনা সর্বদা সঠিক থাকবে।


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

1

আমি এটির জন্য একটি কাজ খুঁজে পেয়েছি। এটি দুর্দান্ত সুন্দর নয়, তবে এটি একটি সুপারক্লাসের মানগুলি না জানার বা ডিফল্ট মান নির্ধারণ করার সমস্যা সমাধান করে।

আপনাকে যা করতে হবে তা হ'ল সাবক্লাসের initডানদিকে সুবিধামত ব্যবহার করে সুপারক্লাসের একটি উদাহরণ তৈরি করা init। তারপরে আপনি সুনির্দিষ্টভাবে সুনির্দিষ্টভাবে initতৈরি করা দৃষ্টান্তটি ব্যবহার করে সুপারকে মনোনীত করেন।

class A {
    var x: Int

    init(x: Int) {
        self.x = x
    }

    convenience init() {
        self.init(x: 0)
    }
}

class B: A {
    init() {
        // calls A's convenience init, gets instance of A with default x value
        let intermediate = A() 

        super.init(x: intermediate.x) 
    }
}

1

আপনার সুবিধাজনক init()থেকে নতুন সহায়ক ফাংশনে প্রারম্ভিককরণের কোডটি বের করার বিষয়ে বিবেচনা করুন foo(), foo(...)আপনার উপ-শ্রেণিতে সূচনা করার জন্য কল করুন ।


ভাল পরামর্শ, কিন্তু এটি আসলে প্রশ্নের উত্তর দেয় না।
সুইফটনামসেক 16

0

প্রারম্ভিকদের এবং তাদের উত্তরাধিকারের গভীরতার জন্য 18:30 এ ডাব্লুডাব্লুডিসি-ভিডিও "403 ইন্টারমিডিয়েট সুইফ্ট" দেখুন। আমি এটি বুঝতে পেরে নিচের বিষয়গুলি বিবেচনা করুন:

class Dragon {
    var legs: Int
    var isFlying: Bool

    init(legs: Int, isFlying: Bool) {
        self.legs = legs
        self.isFlying = isFlying
    }

    convenience initWyvern() { 
        self.init(legs: 2, isFlying: true)
    }
}

তবে এখন একটি Wyrm-subclass বিবেচনা করুন: একটি Wyrm পা এবং পাখা নেই একটি ড্রাগন হয়। সুতরাং একটি ওয়েওয়ারের জন্য ইনিশিয়ালাইজার (2 পা, 2 পাখা) এর জন্য ভুল! যদি ওয়াইভার্ন-ইনিশিয়ালাইজার সুবিধার্থে কেবল কল্পনা না করা যায় তবে কেবলমাত্র পুরোপুরি মনোনীত প্রাথমিক সূচক: ত্রুটিটি এড়ানো যায়:

class Wyrm: Dragon {
    init() {
        super.init(legs: 0, isFlying: false)
    }
}

12
এটি আসলে কোনও কারণ নয়। আমি যখন সাবক্লাসটি বানাবো তখন কি initWyvernবোধগম্য হয়?
সুলতান

4
হ্যাঁ, আমি বিশ্বাসী নই। Wyrmসুবিধাপ্রাপ্তি বলার পরে পাগুলির সংখ্যাটি ওভাররাইড করা থেকে বিরত থাকার কিছুই নেই ।
রবার্ট

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

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

-1

আপনার কেবল দুটি প্রাথমিককর্মী কেন নেই - একটিতে ডিফল্ট মান রয়েছে?

class A {
  var x: Int

  init(x: Int) {
    self.x = x
  }

  init() {
    self.x = 0
  }
}

class B: A {
  override init() {
    super.init()

    // Do something else
  }
}

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