উদ্দেশ্য-সি স্ট্যাটিক শ্রেণির স্তর ভেরিয়েবল vari


143

আমার একটি ক্লাস ফিল্ম রয়েছে যার প্রত্যেকটিরই একটি আলাদা আইডি রয়েছে stores সি # তে, জাভা ইত্যাদিতে আমি একটি স্ট্যাটিক ইন্ট কারেন্টআইডি সংজ্ঞায়িত করতে পারি এবং প্রতিটি সময় আমি আইডি সেট করে আমি বর্তমান আইডিআইডি বাড়াতে পারি এবং পরিবর্তনটি ক্লাস স্তরে অবজেক্ট লেভেলে নয় occurs এটি কি উদ্দেশ্য-সি-তে করা যেতে পারে? আমি এর জন্য উত্তর খুঁজে পাওয়া খুব কঠিন পেয়েছি।

উত্তর:


158

ইস্যুর বিবরণ :

  1. আপনি চান যে আপনার ক্লাসএতে একটি ক্লাসবি ক্লাস ভেরিয়েবল রয়েছে।
  2. আপনি প্রোগ্রামিং ভাষা হিসাবে অবজেক্টিভ-সি ব্যবহার করছেন।
  3. উদ্দেশ্য-সি শ্রেণি ভেরিয়েবলগুলি সি ++ এর মতো সমর্থন করে না।

একটি বিকল্প :

অবজেক্টিভ-সি বৈশিষ্ট্যগুলি ব্যবহার করে একটি শ্রেণীর পরিবর্তনশীল আচরণ অনুকরণ করুন

  1. ClassA.m এর মধ্যে স্থির পরিবর্তনশীল ঘোষণা / সংজ্ঞায়িত করুন সুতরাং এটি কেবলমাত্র ক্লাসএ পদ্ধতিগুলির (এবং আপনি ক্লাসএ.এম এর ভিতরে থাকা সমস্ত কিছু) জন্য অ্যাক্সেসযোগ্য হবে।

  2. ক্লাসবি-এর উদাহরণ সহ স্থির পরিবর্তনশীল একবারে আরম্ভ করার জন্য এনএসবজেক্ট সূচনা ক্লাস পদ্ধতিটি ওভাররাইট করুন।

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

  4. কোনও ক্লাসএ শ্রেণি / উদাহরণ পদ্ধতিতে স্থির পরিবর্তনশীলটি নির্দ্বিধায় ব্যবহার করুন।

কোড নমুনা :

ফাইল: classA.m

static ClassB *classVariableName = nil;

@implementation ClassA

...
 
+(void) initialize
{
    if (! classVariableName)
        classVariableName = [[ClassB alloc] init];
}

+(void) classMethodName
{
    [classVariableName doSomething]; 
}

-(void) instanceMethodName
{
    [classVariableName doSomething]; 
}

...

@end

তথ্যসূত্র :

  1. ক্লাস ভেরিয়েবলগুলি উদ্দেশ্য-সি এবং সি ++ পদ্ধতির তুলনা করে ব্যাখ্যা করেছে

3
ক্লাসএ.এম এর মধ্যে আপনার কাছে টাইপ ক্লাসএ-এর একটি স্ট্যাটিক ভেরিয়েবল থাকতে পারে?
ছাগলছানা

6
এটি একটি নির্বোধ প্রশ্ন হতে পারে তবে কি বলেছে স্মৃতি প্রকাশের? কোনও অ্যাপ্লিকেশন চলমান সময় ধরে এটি বেঁচে থাকতে পারে বলে কিছু যায় আসে না?
সামিক

1
@ সামিক, উদ্দেশ্য-সি দেখুন: স্ট্যাটিক ভেরিয়েবল কেন ধরে রাখবেন? । অবজেক্টের পয়েন্টারটি মোছা যায় না, তবে বস্তু নিজেই পারে। আপনি সম্ভবত এটি প্রকাশ করতে চান না কারণ আপনি সম্ভবত এটি যতক্ষণ না এটি চালু রাখতে চান ততক্ষণ আপনি এটি চালিয়ে যেতে পারেন তবে আপনি মেমরিটি মুক্তি দিলে তা সংরক্ষণ করবেন, তাই যদি আপনি জানেন যে আপনার আর এটির প্রয়োজন নেই, তবে আপনার উচিত এটিকে মুক্ত কর.
ma11hew28

5
যদি ইনিশিয়াল () কেবলমাত্র একবার কল করার নিশ্চয়তা দেওয়া হয় তবে আপনার শর্তাধীন "যদি (! শ্রেণি পরিবর্তনশীল নাম)" দরকার হয় কেন?
জেবি

23
@ জ্যামি, initializeপ্রতিটি ক্লাসের জন্য একবার বলা হয় (সাবক্লাসের আগে সুপারক্লাস), তবে যদি একটি সাবক্লাস ওভাররাইড না করে initializeতবে প্যারেন্ট ক্লাসটি initializeআবার কল হবে। অতএব, আপনি যদি সেই কোডটি দুটিবার সম্পাদন করতে না চান তবে একজন গার্ডের প্রয়োজন। অ্যাপলের উদ্দেশ্য-সি ডক্সে একটি শ্রেণীর অবজেক্টের সূচনা দেখুন ।
big_m

31

এক্সকোড 8 হিসাবে, আপনি ওবজে-সি শ্রেণীর বৈশিষ্ট্য নির্ধারণ করতে পারেন। এটি সুইফ্টের স্ট্যাটিক বৈশিষ্ট্যগুলির সাথে আন্তঃব্যবহার করতে যুক্ত করা হয়েছে।

উদ্দেশ্য-সি এখন শ্রেণীর বৈশিষ্ট্যগুলিকে সমর্থন করে, যা সুইফ্ট প্রকারের বৈশিষ্ট্যগুলির সাথে আন্তঃব্যবহার করে। তাদের হিসাবে ঘোষণা করা হয়েছে: @ প্রপার্টি (শ্রেণি) এনএসএসআর্টিং * কিছু স্ট্রিংপ্রপার্টি;। এগুলি কখনই সংশ্লেষিত হয় না। (23891898)

এখানে একটি উদাহরণ

@interface YourClass : NSObject

@property (class, nonatomic, assign) NSInteger currentId;

@end

@implementation YourClass

static NSInteger _currentId = 0;

+ (NSInteger)currentId {
    return _currentId;
}

+ (void)setCurrentId:(NSInteger)newValue {
    _currentId = newValue;
}

@end

তারপরে আপনি এটির মতো অ্যাক্সেস করতে পারবেন:

YourClass.currentId = 1;
val = YourClass.currentId;

এই পুরাতন উত্তরটি সম্পাদনা করার জন্য আমি এখানে একটি খুব আকর্ষণীয় ব্যাখ্যামূলক পোস্ট উল্লেখ করেছি।


২০১১ উত্তর: (এটি ব্যবহার করবেন না, এটি ভয়ানক)

আপনি যদি সত্যিই কোনও বিশ্বব্যাপী পরিবর্তনশীল ঘোষণা করতে না চান, তবে অন্য একটি বিকল্প রয়েছে, সম্ভবত খুব গোঁড়া :-) নয়, তবে কাজ করে ... আপনি অভ্যন্তরীণ স্থিতিশীল ভেরিয়েবল সহ "গেট অ্যান্ড সেট" পদ্ধতিটি ঘোষণা করতে পারেন:

+ (NSString*)testHolder:(NSString*)_test {
    static NSString *test;

    if(_test != nil) {
        if(test != nil)
            [test release];
        test = [_test retain];
    }

    // if(test == nil)
    //     test = @"Initialize the var here if you need to";

    return test;
}

সুতরাং, যদি আপনার মানটি পেতে হয় তবে কেবল কল করুন:

NSString *testVal = [MyClass testHolder:nil]

এবং তারপরে, আপনি যখন এটি সেট করতে চান:

[MyClass testHolder:testVal]

আপনি যদি এই সিউডো-স্ট্যাটিক-ভার নির্ধারণ করতে সক্ষম হতে চান তবে আপনি এটি testHolderহিসাবে ঘোষণা করতে পারেন :

+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
    static NSString *test;

    if(shouldSet) {
        if(test != nil)
            [test release];
        test = [_test retain];
    }

    return test;
}

এবং দুটি সহজ পদ্ধতি:

+ (NSString*)test {
    return [MyClass testHolderSet:NO newValue:nil];
}

+ (void)setTest:(NSString*)_test {
    [MyClass testHolderSet:YES newValue:_test];
}

আশা করি এটা সাহায্য করবে! শুভকামনা।


দুর্দান্ত, তবে এটি সত্যিই কোনও বৈশ্বিক পরিবর্তনশীল নয় কারণ এটি অন্যান্য .mফাইল থেকে অ্যাক্সেস করা যায় না এবং আমি মনে করি এটি Class.mফাইলের মধ্যে "গ্লোবাল" হওয়া ভাল ।
ma11hew28

29

আপনার .m ফাইলে, আপনি স্থির হিসাবে একটি চলক ঘোষণা করতে পারেন:

static ClassName *variableName = nil;

তারপরে আপনি এটি আপনার +(void)initializeপদ্ধতিতে শুরু করতে পারেন ।

দয়া করে নোট করুন যে এটি একটি সরল সি স্ট্যাটিক পরিবর্তনশীল এবং এটি জাভা বা সি # বিবেচনায় স্থির নয়, তবে একই রকম ফলাফল পাবে।


16

আপনার .m ফাইলে কোনও ফাইলকে বিশ্বব্যাপী ভেরিয়েবল ঘোষণা করুন:

static int currentID = 1;

তারপরে আপনার আর্ট রুটিনে, উল্লেখ করুন:

- (id) init
{
    self = [super init];
    if (self != nil) {
        _myID = currentID++; // not thread safe
    }
    return self;
}

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


11

পিজিবি যেমন বলেছে, কোনও "শ্রেণীর ভেরিয়েবল," কেবল "ইনস্ট্যান্স ভেরিয়েবল নেই। ক্লাস ভেরিয়েবলগুলি করার উদ্দেশ্য-সি উপায়টি ক্লাসের .m ফাইলের অভ্যন্তরে একটি স্থিতিশীল বৈশ্বিক পরিবর্তনশীল। "স্ট্যাটিক" নিশ্চিত করে যে ভেরিয়েবলটি সেই ফাইলের বাইরে ব্যবহার করা যাবে না (যেমন এটি বাহ্যিক হতে পারে না)।


3

এখানে একটি বিকল্প হবে:

+(int)getId{
    static int id;
    //Do anything you need to update the ID here
    return id;
}

নোট করুন যে এই পদ্ধতিটি আইডি অ্যাক্সেসের একমাত্র পদ্ধতি হবে, সুতরাং আপনাকে এই কোডটিতে কোনওভাবে এটি আপডেট করতে হবে।


2

(কঠোরভাবে প্রশ্নের উত্তর না দিয়ে কথা বলছি, তবে ক্লাস ভেরিয়েবলগুলি সন্ধান করার ক্ষেত্রে আমার অভিজ্ঞতায় কার্যকর হতে পারে)

একটি শ্রেণি পদ্ধতি প্রায়শই অন্যান্য ভাষায় ক্লাস ভেরিয়েবলের অনেক ভূমিকা পালন করতে পারে (যেমন পরীক্ষার সময় কনফিগারেশন পরিবর্তিত হয়):

@interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
@end
@implementation
+ (NSString*)theNameThing { return @"Something general"; }
- (void)doTheThing {
  [SomeResource changeSomething:[self.class theNameThing]];
}
@end

@interface MySpecialCase: MyCls
@end
@implementation
+ (NSString*)theNameThing { return @"Something specific"; }
@end

এখন, শ্রেণীর একটি অবজেক্ট MyClsকল Resource:changeSomething:করার জন্য স্ট্রিং সহ @"Something general"কল করে doTheThing:, তবে MySpecialCaseস্ট্রিংয়ের সাথে উত্পন্ন একটি বস্তু @"Something specific"


0

আপনি ক্লাসের নামটি ClassA.mm হিসাবে রাখতে পারেন এবং এতে C ++ বৈশিষ্ট্য যুক্ত করতে পারেন।


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