সম্পত্তি প্রাপ্তি এবং সেটার


194

এই সাধারণ ক্লাসের সাথে আমি সংকলক সতর্কতা পাচ্ছি

xনিজস্ব সেটার / গেটারের মধ্যে পরিবর্তন / অ্যাক্সেসের চেষ্টা করা হচ্ছে

এবং যখন আমি এটির মতো এটি ব্যবহার করি:

var p: point = Point()
p.x = 12

আমি একটি EXC_BAD_ACCESS পাই। সুস্পষ্ট ব্যাকিং আইভারগুলি ছাড়াই আমি কীভাবে এটি করতে পারি?

class Point {

    var x: Int {
        set {
            x = newValue * 2 //Error
        }
        get {
            return x / 2 //Error
        }
    }
    // ...
}

1
এমনটি করার ফলে সংকলকটিতে অতিরিক্ত চাপ পড়বে এবং সিপিইউ জোর করে গ্রাস করবে। আমি সবেমাত্র এটি করেছি: | । এটি আমি তৈরি করছিলাম ত্রুটি। (আমি খেলার মাঠ ব্যবহার করছিলাম)
মধু

এই আচরণটি বিভ্রান্তিকর, এর পরিবর্তে setআপনি ব্যবহার করতে চান didSet। আপনি যখন প্রয়োগ করবেন তখন সম্পত্তিগুলি অবজেক্টিভ-সি বা অন্যান্য ভাষার চেয়ে সুইফটে আলাদা আচরণ করে set। দেখুন @jack থেকে নিচে উত্তর এবং একটি উদাহরণ didSet@cSquirrel থেকে
পল Solt

উত্তর:


232

সেটেটর এবং গেটার্স প্রয়োগ হয় computed properties; যেমন বৈশিষ্ট্যগুলিতে উদাহরণস্বরূপ স্টোরেজ নেই - গেটর থেকে প্রাপ্ত মানটি অন্য উদাহরণের বৈশিষ্ট্য থেকে গণনা করা। আপনার ক্ষেত্রে, xনিয়োগের কোনও দরকার নেই ।

স্পষ্টত: "আমি স্পষ্টভাবে ব্যাকিং আইভারগুলি ছাড়াই এটি কীভাবে করতে পারি"। আপনি পারবেন না - গণিত সম্পত্তি ব্যাকআপ করার জন্য আপনার কিছু প্রয়োজন । এটা চেষ্টা কর:

class Point {
  private var _x: Int = 0             // _x -> backingX
  var x: Int {
    set { _x = 2 * newValue }
    get { return _x / 2 }
  }
}

বিশেষত, সুইফট আরএপিএলে:

 15> var pt = Point()
pt: Point = {
  _x = 0
}
 16> pt.x = 10
 17> pt
$R3: Point = {
  _x = 20
}
 18> pt.x
$R4: Int = 10

106

সুইফটে সেটেটর / গেটার্স ওবিজিসির চেয়ে বেশ আলাদা। সম্পত্তি একটি হয়ে কম্পিউটেড সম্পত্তি এটি নেই যার মানে না এর মত ব্যাকিং পরিবর্তনশীল আছে _xএটা ObjC মধ্যে would হিসাবে।

নীচের সমাধান কোডে আপনি দেখতে পাচ্ছেন যে xTimesTwoকোনও কিছু সঞ্চয় করে না , তবে কেবল ফলাফলটি গণনা করে x

গণিত বৈশিষ্ট্যের উপর অফিসিয়াল ডক্স দেখুন ।

আপনি যে কার্যকারিতাটি চান তা সম্পত্তি পর্যবেক্ষকও হতে পারে ।

আপনার যা প্রয়োজন তা হ'ল:

var x: Int

var xTimesTwo: Int {
    set {
       x = newValue / 2
    }
    get {
        return x * 2
    }
}

আপনি সেটার / গেটারগুলির মধ্যে অন্যান্য বৈশিষ্ট্যগুলি সংশোধন করতে পারেন, এটি তাদের জন্য যা বোঝায়।


1
হ্যাঁ, ডকুমেন্টেশনে আমি এটিই পড়ছি। আমি সম্পত্তি বিভাগটি এড়িয়ে গিয়েছিলাম এবং মনে হচ্ছে এটির কোনও উপায় নেই, তাই না?
এটমিক্স

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

5
আপনি এটি ব্যবহার করতে পারেন didSetযা এটি সেট হওয়ার সাথে সাথেই মানটি পরিবর্তন করতে দেয়। যদিও পাওয়ার জন্য কিছুই নেই ...
ObjectiveCsam

1
দ্রষ্টব্য: আপনি যদি মানটি পূর্বাবস্থায় ফিরিয়ে আনতে চান কারণ এটি অবৈধ ইনপুট ছিল, আপনাকে অবশ্যই এতে xফিরে যেতে oldValueহবে didSet। আচরণের এই পরিবর্তনটি উদ্দেশ্যমূলক-সি বৈশিষ্ট্যগুলি থেকে আসা খুব বিভ্রান্তিকর, ধন্যবাদ!
পল সোল্ট

105

আপনি সম্পত্তি পর্যবেক্ষক ব্যবহার করে সেট মানটি কাস্টমাইজ করতে পারেন। এটি করতে 'সেট' এর পরিবর্তে 'didSet' ব্যবহার করুন।

class Point {

var x: Int {
    didSet {
        x = x * 2
    }
}
...

গেটর হিসাবে ...

class Point {

var doubleX: Int {
    get {
        return x / 2
    }
}
...

আপনি কীভাবে xএই প্যাটার্নটিতে একটি ডিফল্ট মান দিয়ে শুরু করতে পারেন ?
i_am_jorf

3
আমি দেখতে, এটা হতে হবে: var x: Int = 0 { didSet { ...
i_am_jorf

31

GoZoner এর উত্তরে বিস্তারিত জানাতে:

এখানে আপনার আসল সমস্যাটি হ'ল আপনি পুনরাবৃত্তভাবে আপনার গেটারকে কল করছেন।

var x:Int
    {
        set
        {
            x = newValue * 2 // This isn't a problem
        }
        get {
            return x / 2 // Here is your real issue, you are recursively calling 
                         // your x property's getter
        }
    }

উপরের মতামত কোডের পরামর্শ অনুসারে, আপনি x সম্পত্তিটির প্রাপ্তকারীকে অসীম কল করছেন, যা আপনি একটি এক্সসি_বিএডি_এসিসিএস কোড না পাওয়া পর্যন্ত চালানো চালিয়ে যাবেন (আপনি আপনার এক্সকোডের খেলার মাঠের পরিবেশের নীচে ডানদিকে স্পিনার দেখতে পাবেন)।

সুইফ্ট ডকুমেন্টেশন থেকে উদাহরণটি বিবেচনা করুন :

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

লক্ষ্য করুন যে কেন্দ্রের গণিত সম্পত্তি কখনই ভেরিয়েবলের ঘোষণায় নিজেকে পরিবর্তন করে না বা ফেরত দেয়।


থাম্বের বিধিটি কখনও প্রাপ্তির অর্থের মধ্যে থেকে সম্পত্তিটিকে নিজেই অ্যাক্সেস করতে পারে নাget । কারণ এটি অন্যকে getট্রিগার করবে যা অন্যকে ট্রিগার করবে। । । এমনকি এটি প্রিন্ট করবেন না। কারণ মুদ্রণের জন্য এটি মুদ্রণের আগে মানটি 'পাওয়ার' দরকার!
মধু

19

ওভাররাইড করতে setterএবং getterদ্রুত পরিবর্তনগুলির জন্য নীচের প্রদত্ত কোডটি ব্যবহার করুন

var temX : Int? 
var x: Int?{

    set(newX){
       temX = newX
    }

    get{
        return temX
    }
}

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

আমরা সেটারটিকে সহজভাবে অনুরোধ করতে পারি

x = 10

প্রদত্ত কোডের নীচে লাইন ফায়ারিংয়ের জন্য অনুরোধ করা হবে

var newVar = x

8

আপনি পুনরাবৃত্তিx সঙ্গে সংজ্ঞা দিচ্ছেন x। যেন কেউ আপনাকে জিজ্ঞেস করে তোমার বয়স কত? এবং আপনি উত্তর দিন "আমি আমার বয়সের দ্বিগুণ"। যা অর্থহীন।

আপনারা অবশ্যই বলবেন যে আমি জন এর বয়সের বা অন্য কোনও পরিবর্তনশীল তবে নিজেকে twice

গণিত ভেরিয়েবলগুলি সর্বদা অন্য ভেরিয়েবলের উপর নির্ভরশীল।


থাম্বের বিধিটি কখনও প্রাপ্তির অর্থের মধ্যে থেকে সম্পত্তিটিকে নিজেই অ্যাক্সেস করতে পারে নাget । কারণ এটি অন্যকে getট্রিগার করবে যা অন্যকে ট্রিগার করবে। । । এমনকি এটি প্রিন্ট করবেন না। কারণ মুদ্রণের জন্য এটি মুদ্রণের আগে মানটি 'পাওয়ার' দরকার!

struct Person{
    var name: String{
        get{
            print(name) // DON'T do this!!!!
            return "as"
        }
        set{
        }
    }
}

let p1 = Person()

যেহেতু নিম্নলিখিত সতর্কতা দিতে হবে:

এটির নিজের গেটারের মধ্যে থেকে 'নাম' অ্যাক্সেস করার চেষ্টা করা হচ্ছে।

ত্রুটিটি দেখতে অস্পষ্ট দেখাচ্ছে:

এখানে চিত্র বর্ণনা লিখুন

বিকল্প হিসাবে আপনি ব্যবহার করতে পারেন didSet। এর সাথে didSetআপনি যে মানটি আগে সেট করা হয়েছিল এবং এখনই সেট হয়ে গেছে তা ধরে রাখতে। আরও উত্তর দেখুন


8

আপডেট: সুইফট 4

নীচের ক্লাসে সেটার এবং গেটরটি ভেরিয়েবলের জন্য প্রয়োগ করা হয় sideLength

class Triangle: {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) { //initializer method
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
        get { // getter
            return 3.0 * sideLength
        }
        set(newValue) { //setter
            sideLength = newValue / 4.0
        }
   }

অবজেক্ট তৈরি করা হচ্ছে

var triangle = Triangle(sideLength: 3.9, name: "a triangle")

গেটার

print(triangle.perimeter) // invoking getter

গোয়েন্দা

triangle.perimeter = 9.9 // invoking setter

6

এটি ব্যবহার করার চেষ্টা করুন:

var x:Int!

var xTimesTwo:Int {
    get {
        return x * 2
    }
    set {
        x = newValue / 2
    }
}

এটি মূলত জ্যাক উয়ের উত্তর, তবে পার্থক্যটি হ'ল জ্যাক উয়ের উত্তরে তার এক্স ভেরিয়েবলটি var x: Intআমার ক্ষেত্রে আমার এক্স ভেরিয়েবলটি এর মতো:, var x: Int!তাই আমি যা করেছি তা এটিকে একটি optionচ্ছিক প্রকার হিসাবে তৈরি করা হয়েছিল।


1

সুইফ্ট 5.1 এর জন্য আপডেট

সুইফট 5.1 এর হিসাবে আপনি এখন ব্যবহার না করে আপনার পরিবর্তনশীল পেতে পারেন পেতে শব্দ। উদাহরণ স্বরূপ:

var helloWorld: String {
"Hello World"
}

আমি যদি পরিবর্তন করার চেষ্টা করি, হ্যালো ওয়ার্ল্ড = "ম্যাকওয়ার্ড" , মানটি বরাদ্দ করতে পারছি না: 'হ্যালো ওয়ার্ল্ড' একটি গেট-ওয়ান প্রোপার্টি ত্রুটি দেখাচ্ছে।
ম্যাকডোনাল_11

নতুন মান নির্ধারণ করা কি সম্ভব? অথবা না ?
ম্যাকডোনাল_11

এটা সম্ভব বলে আমি মনে করি না।
অটলায়াস

তাই আক্ষরিক অর্থে, হ্যালো হলেন ওয়ার্ল্ড: স্ট্রিং Hello "হ্যালো ওয়ার্ল্ড"} এবং, হ্যালো ওয়ার্ল্ড: স্ট্রিং = "হ্যালো ওয়ার্ল্ড" একই?
ম্যাকডোনাল_11

হ্যাঁ আমি তাই মনে করি.
আটলাসা

0

সুইফটে সেটেটর এবং গেটারগণ গণিত বৈশিষ্ট্য / ভেরিয়েবলগুলিতে প্রয়োগ করে। এই বৈশিষ্ট্যগুলি / ভেরিয়েবলগুলি আসলে মেমোরিতে সংরক্ষণ করা হয় না, বরং সঞ্চিত বৈশিষ্ট্য / ভেরিয়েবলের মানের ভিত্তিতে গণনা করা হয়।

বিষয়টিতে অ্যাপলের সুইফ্ট ডকুমেন্টেশন দেখুন: সুইফ্ট পরিবর্তনশীল ঘোষণা


0

এখানে একটি তাত্ত্বিক উত্তর। এখানে পাওয়া যাবে

একটি {get সেট} সম্পত্তি ধ্রুবক সঞ্চিত সম্পত্তি হতে পারে না। এটি একটি গণিত সম্পত্তি হতে হবে এবং গেট অ্যান্ড সেট উভয়ই প্রয়োগ করা উচিত।

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