properties - সুইফ্ট ক্লাসে ত্রুটি: সম্পত্তি super.init কল এ শুরু হয় না




compiler-errors swift (8)

Ugly বিন্যাস জন্য দুঃখিত। ঘোষণার পরে শুধু একটি প্রশ্ন চরিত্র রাখুন এবং সবকিছু ঠিক থাকবে। একটি প্রশ্ন কম্পাইলার যে মান ঐচ্ছিক বলে।

class Square: Shape {
    var sideLength: Double?   // <=== like this ..

    init(sideLength:Double, name:String) {
        super.init(name:name) // Error here
        self.sideLength = sideLength
        numberOfSides = 4
    }
    func area () -> Double {
        return sideLength * sideLength
    }
}

Edit1:

এই ত্রুটি উপেক্ষা করার জন্য একটি ভাল উপায় আছে। জমাসচাদের মন্তব্য অনুযায়ী আপনার ক্ষেত্রে ঐচ্ছিক ব্যবহার করার কোন কারণ নেই কারণ বিকল্পগুলি ব্যবহারে আরামদায়ক নয় এবং আপনাকে সর্বদা এটি অ্যাক্সেস করার পূর্বে ঐচ্ছিক নয় কিনা তা যাচাই করতে হবে। তাই আপনাকে কেবল ঘোষণা করতে হবে সদস্য ঘোষণার পরে সদস্য আরম্ভ করা:

class Square: Shape {
    var sideLength: Double=Double()   

    init(sideLength:Double, name:String) {
        super.init(name:name)
        self.sideLength = sideLength
        numberOfSides = 4
    }
    func area () -> Double {
        return sideLength * sideLength
    }
}

Edit2:

দুই মিনিট পর এই উত্তর পেয়েছিলাম আমি আরও ভাল উপায় খুঁজে পেয়েছি। আপনি যদি আপনার কন্সট্রকটারে ক্লাস সদস্যকে প্রাথমিকভাবে শুরু করতে চান তবে আপনাকে অবশ্যই অবদানকারীর ভিতরে এবং super.init () কল এর আগে প্রাথমিক মান নির্ধারণ করতে হবে। এটার মত:

class Square: Shape {
    var sideLength: Double  

    init(sideLength:Double, name:String) {
        self.sideLength = sideLength   // <= before super.init call..
        super.init(name:name)
        numberOfSides = 4
    }
    func area () -> Double {
        return sideLength * sideLength
    }
}

সুইফ্ট শেখার শুভেচ্ছা।

আমি দুটি ক্লাস, Shape এবং Square

class Shape {
    var numberOfSides = 0
    var name: String
    init(name:String) {
        self.name = name
    }
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

class Square: Shape {
    var sideLength: Double

    init(sideLength:Double, name:String) {
        super.init(name:name) // Error here
        self.sideLength = sideLength
        numberOfSides = 4
    }
    func area () -> Double {
        return sideLength * sideLength
    }
}

উপরে বাস্তবায়ন সঙ্গে আমি ত্রুটি পেতে:

property 'self.sideLength' not initialized at super.init call
    super.init(name:name)

কেন আমি self.sideLength কল করার আগে super.init self.sideLength সেট করতে হবে?


আপনার সমস্ত ইনস্ট্যান্স ভেরিয়েবলগুলি সূচনা করার পরে "super.init ()" বলা উচিত।

অ্যাপল এর "ইন্টারমিডিয়েট সুইফ্ট" ভিডিওতে (আপনি এটি অ্যাপল বিকাশকারী ভিডিও সংস্থান পৃষ্ঠা https://developer.apple.com/videos/wwdc/2014/ এ খুঁজে পেতে পারেন), প্রায় 28:40 এ, এটি স্পষ্টভাবে বলা হয়েছে যে সকল প্রারম্ভিক আপনি আপনার ইনস্ট্যান্স ভেরিয়েবল আরম্ভ করার পরে সুপার ক্লাস বলা উচিত।

Objective-C তে এটি বিপরীত ছিল। সুইফ্টে, যেহেতু এটি ব্যবহার করার আগে সমস্ত বৈশিষ্ট্যগুলি প্রাথমিকভাবে চালু করা দরকার, তাই আমাদের প্রথমে বৈশিষ্ট্যগুলি শুরু করতে হবে। এটি প্রথম শ্রেণির সূচনা না করেই সুপার ক্লাসের "init ()" পদ্ধতি থেকে বর্ধিত ফাংশনকে কল করতে বাধা দেয়।

সুতরাং "স্কোয়ার" বাস্তবায়ন করা উচিত:

class Square: Shape {
    var sideLength: Double

    init(sideLength:Double, name:String) {
        self.sideLength = sideLength
        numberOfSides = 4
        super.init(name:name) // Correct position for "super.init()"
    }
    func area () -> Double {
        return sideLength * sideLength
    }
}

এটি একটি staggeringly মূঢ় নকশা।

এই মত কিছু বিবেচনা করুন:

.
.
.
var playerShip:PlayerShip
var deltaPoint = CGPointZero

init(size: CGSize)
{
    super.init(size: size)
    playerShip = PlayerShip(pos: CGPointMake(self.size.width / 2.0, 100))
    playerLayerNode.addChild(playerShip)        
}
.
.
.

উপরে উল্লেখিত হিসাবে, এই অবৈধ। কিন্তু তাই হয়:

.
.
.
var playerShip:PlayerShip = PlayerShip(pos: CGPointMake(self.size.width / 2.0, 100))
var deltaPoint = CGPointZero

init(size: CGSize)
{
    super.init(size: size)
    playerLayerNode.addChild(playerShip)        
}
.
.
.

কারণ 'স্ব' শুরু করা হয়নি।

আমি আন্তরিকভাবে আশা করি এই বাগ শীঘ্রই সংশোধন করা হয়েছে।

(হ্যাঁ আমি জানি যে আমি একটি খালি বস্তু তৈরি করতে পারি এবং তারপর আকার সেট করতে পারি তবে এটি কেবল মূঢ়)।


এডওয়ার্ড

আপনি আপনার উদাহরণে এই কোডটি সংশোধন করতে পারেন:

var playerShip:PlayerShip!
var deltaPoint = CGPointZero

init(size: CGSize)
{
    super.init(size: size)
    playerLayerNode.addChild(playerShip)        
}

এটি একটি নিখুঁতভাবে unwrapped ঐচ্ছিক ব্যবহার করা হয়।

ডকুমেন্টেশন মধ্যে আমরা পড়তে পারেন:

"বিকল্পগুলির সাথে, যদি আপনি একটি প্রারম্ভিকভাবে অপ্রচলিত ঐচ্ছিক পরিবর্তনশীল বা সম্পত্তি ঘোষণা করার সময় একটি প্রাথমিক মান প্রদান না করেন তবে এটি স্বয়ংক্রিয়ভাবে মূল্যকে ডিফল্ট হিসাবে ডিফল্ট করে।"


দ্রুত / কখনও কখনও ব্যবহার করা যেতে পারে আগে প্রতিটি সদস্য var শুরু করতে আপনি দ্রুত। যেহেতু এটি সুপারগুলি চালু হলে এটি কী হতে পারে তা নিশ্চিত করা যায় না, এটি ত্রুটিযুক্ত: দুঃখিত হওয়ার চেয়ে নিরাপদ


সুইফ্ট আপনাকে বৈশিষ্ট্যাবলী শুরু করার সাথে সাথে সুপার ক্লাস শুরু করতে দেয় না, ওবজ সি এর বিপরীত। সুতরাং আপনাকে "super.init" কল করার আগে সমস্ত বৈশিষ্ট্যগুলি শুরু করতে হবে।

অনুগ্রহ করে http://blog.scottlogic.com/2014/11/20/swift-initialisation.html যান। এটি আপনার সমস্যার একটি চমৎকার ব্যাখ্যা দেয়।


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

চলুন একটি বস্তু এ গ্রহণ করা যাক আমরা নিম্নরূপ এটি সংজ্ঞায়িত করব।

class A {
    var x: Int
    init(x: Int) {
        self.x = x
    }
}

লক্ষ্য করুন যে A একটি superclass নেই, তাই এটি একটি super.init () ফাংশন কল করতে পারে না কারণ এটি বিদ্যমান নয়।

ঠিক আছে, তাই এখন বি নামক একটি নতুন ক্লাসের সাথে সাবক্লাস A কে আসুন।

class B: A {
    var y: Int
    init(x: Int, y: Int) {
        self.y = y
        super.init(x: x)
    }
}

এটি উদ্দেশ্য-সি থেকে একটি প্রস্থান যেখানে [super init] সাধারণত অন্য কিছু আগে প্রথম বলা হবে। তাই না সুইফ্ট। আপনি কলিং পদ্ধতি সহ (আপনার সুপারক্লাস 'প্রাথমিকতা অন্তর্ভুক্ত) সহ অন্য কিছু করার আগে আপনার ইনস্ট্যান্স ভেরিয়েবলগুলি সামঞ্জস্যপূর্ণ অবস্থায় রয়েছে তা নিশ্চিত করার জন্য আপনি দায়ী।


docs থেকে

নিরাপত্তা চেক 1

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

কেন আমরা এই ধরনের একটি নিরাপত্তা চেক প্রয়োজন?

এই উত্তর দিতে তাত্ক্ষণিকভাবে শুরু প্রক্রিয়ার যদিও যেতে দেয়।

দুই ধাপের সূচনা

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

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

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

নিরাপত্তা চেক 1

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

এখন, দুইটি পর্যায়ে প্রাথমিকভাবে কোনও আদেশের কথা বলা হয় না, তবে এই সুরক্ষা super.init , সমস্ত সম্পত্তিগুলির সূচনা করার পরে super.init আদেশ দেওয়া শুরু করে।

সুরক্ষা পরীক্ষা 1টি অপ্রাসঙ্গিক বলে মনে হতে পারে, দুই-পর্যায়ে সূচনাটি সম্পত্তির মানগুলিকে অ্যাক্সেস করা থেকে আগে অ্যাক্সেস করা থেকে সরাতে পারে সেগুলি সন্তুষ্ট হতে পারে, এই সুরক্ষা যাচাই ছাড়াই 1।

এই নমুনা মত

class Shape {
    var name: String
    var sides : Int
    init(sides:Int, named: String) {
        self.sides = sides
        self.name = named
    }
}

class Triangle: Shape {
    var hypotenuse: Int
    init(hypotenuse:Int) {
        super.init(sides: 3, named: "Triangle") 
        self.hypotenuse = hypotenuse
    }
}

Triangle.init ব্যবহার করা হচ্ছে আগে, প্রতিটি সম্পত্তি শুরু হয়েছে। তাই নিরাপত্তা চেক 1 অপ্রাসঙ্গিক বলে মনে হচ্ছে,

কিন্তু তারপর অন্য দৃশ্যকল্প হতে পারে, একটু জটিল,

class Shape {
    var name: String
    var sides : Int
    init(sides:Int, named: String) {
        self.sides = sides
        self.name = named
        printShapeDescription()
    }
    func printShapeDescription() {
        print("Shape Name :\(self.name)")
        print("Sides :\(self.sides)")
    }
}

class Triangle: Shape {
    var hypotenuse: Int
    init(hypotenuse:Int) {
        self.hypotenuse = hypotenuse
        super.init(sides: 3, named: "Triangle")
    }

    override func printShapeDescription() {
        super.printShapeDescription()
        print("Hypotenuse :\(self.hypotenuse)")
    }
}

let triangle = Triangle(hypotenuse: 12)

আউটপুট:

Shape Name :Triangle
Sides :3
Hypotenuse :12

এখানে super.init সেটিং করার আগে আমরা super.init ফোন করেছি, তাহলে super.init কলটি printShapeDescription() নামে পরিচিত হবে এবং যেহেতু এটি ওভাররাইড করা হয়েছে, এটি প্রথম printShapeDescription() এর ট্রায়াঙ্গল শ্রেণী বাস্তবায়নে printShapeDescription() । ট্রায়াঙ্গল ক্লাসের printShapeDescription() কোনও ঐচ্ছিক সম্পত্তি hypotenuse অ্যাক্সেস করে যা এখনও শুরু হয়নি। এবং এটি দুই-পর্যায়ে প্রাথমিকভাবে শুরু হওয়ার আগে সম্পত্তি মানগুলি অ্যাক্সেস করা থেকে আটকানো হিসাবে অনুমোদিত নয়

সুতরাং নিশ্চিত করুন যে দুটি পর্যায় সূচনা সংজ্ঞায়িত হিসাবে সম্পন্ন করা হয়েছে, super.init কল করার একটি নির্দিষ্ট আদেশ থাকা super.init এবং সেটি হল self শ্রেণির দ্বারা উপস্থাপিত সমস্ত বৈশিষ্ট্যগুলি সূচনা করার পরে, আমাদের একটি নিরাপত্তা পরীক্ষা 1





swift