উদ্দেশ্য-সি তে একটি বিমূর্ত শ্রেণি তৈরি করা class


507

আমি মূলত একটি জাভা প্রোগ্রামার যিনি এখন উদ্দেশ্য-সি এর সাথে কাজ করেন works আমি একটি বিমূর্ত শ্রেণি তৈরি করতে চাই, তবে এটি উদ্দেশ্য-সি তে সম্ভব বলে মনে হচ্ছে না। এটা কি সম্ভব?

যদি তা না হয় তবে আমি অবজেক্ট-সিতে কতটা বিমূর্ত শ্রেণির কাছাকাছি যেতে পারি?


18
নীচের উত্তরগুলি দুর্দান্ত। আমি এটি দেখতে পেয়েছি যে বিমূর্ত শ্রেণীর বিষয়টি বেসরকারী পদ্ধতিগুলির সাথে জড়িত - উভয়ই ক্লায়েন্ট কোড কী করতে পারে তা সীমাবদ্ধ করার পদ্ধতি এবং উভয়ই উদ্দেশ্য-সিতে বিদ্যমান। আমি মনে করি এটি বুঝতে সাহায্য করে যে ভাষাটির মানসিকতা নিজেই জাভা থেকে মূলত পৃথক। আমার উত্তরটি দেখুন: স্ট্যাকওভারফ্লো.com
কুইন টেলর

অন্যান্য ভাষার বিপরীতে উদ্দেশ্যমূলক-সি সম্প্রদায়ের মানসিকতা সম্পর্কিত তথ্যের জন্য ধন্যবাদ। এটি সত্যিই আমার সাথে সম্পর্কিত অনেকগুলি প্রশ্নের সমাধান করে (যেমন ব্যক্তিগত পদ্ধতিগুলির জন্য কোনও সরল পদ্ধতি কেন নয়))।
জোনাথন আরবোগাস্ট

1
তাই কোকোদেব সাইটটি দেখুন যা এটি একটি জাভা তুলনা দেয় কোকোএডেভ

2
যদিও ব্যারি এটিকে চিন্তার পরে হিসাবে উল্লেখ করেছেন (আমি যদি এটি ভুলভাবে পড়ছি তবে আমাকে ক্ষমা করুন), আমি মনে করি আপনি উদ্দেশ্য সিতে একটি প্রোটোকল সন্ধান করছেন , উদাহরণস্বরূপ, একটি প্রোটোকল কী?
jww

উত্তর:


633

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

[NSException raise:NSInternalInconsistencyException 
            format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];

যদি আপনার পদ্ধতিটি কোনও মান দেয় তবে এটি ব্যবহার করা কিছুটা সহজ

@throw [NSException exceptionWithName:NSInternalInconsistencyException
                               reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
                             userInfo:nil];

এরপরে আপনাকে পদ্ধতি থেকে কোনও রিটার্ন বিবৃতি যোগ করার দরকার নেই।

যদি বিমূর্ত শ্রেণিটি সত্যিই একটি ইন্টারফেস হয় (যার কোনও কংক্রিট পদ্ধতি বাস্তবায়ন থাকে না), তবে একটি উদ্দেশ্য-সি প্রোটোকল ব্যবহার করা আরও উপযুক্ত বিকল্প appropriate


18
আমি মনে করি যে উত্তরের সবচেয়ে উপযুক্ত অংশটি উল্লেখ করেছে যে আপনি কেবল পদ্ধতিগুলি সংজ্ঞায়িত করার পরিবর্তে @ প্রোটোকল ব্যবহার করতে পারেন।
চাদ স্টুয়ার্ট

13
স্পষ্ট করার জন্য: আপনি একটি সংজ্ঞায় পদ্ধতিগুলি ঘোষণা@protocol করতে পারেন, তবে আপনি সেখানে পদ্ধতিগুলি সংজ্ঞায়িত করতে পারবেন না।
রিচার্ড

এনএসইেক্সেপশনে একটি বিভাগ পদ্ধতি সহ এটি + (instancetype)exceptionForCallingAbstractMethod:(SEL)selectorখুব সুন্দরভাবে কাজ করে।
প্যাট্রিক পিজনাপেল

আইএমএইচও থেকে এই বিষয়টি আমার পক্ষে কার্যকর হয়েছিল, অন্য বিকাশকারীদের কাছে একটি ব্যতিক্রম ছুঁড়ে দেওয়া আরও স্পষ্ট যে এটি এর চেয়ে পছন্দসই আচরণ doesNotRecognizeSelector
ক্রিস

প্রোটোকল (সম্পূর্ণ বিমূর্ত শ্রেণীর জন্য) বা টেম্পলেট পদ্ধতি প্যাটার্ন ব্যবহার করুন যেখানে বিমূর্ত শ্রেণীর আংশিক বাস্তবায়ন / প্রবাহ যুক্তিযুক্ত রয়েছে এখানে স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 8146439 /… দেওয়া আছে । আমার উত্তর নীচে দেখুন।
hadaytullah

267

না, অবজেক্টিভ-সি-তে কোনও বিমূর্ত শ্রেণি তৈরির উপায় নেই।

আপনি একটি বিমূর্ত শ্রেণিকে বিদ্রূপ করতে পারেন - পদ্ধতিগুলি / নির্বাচকদের ডটনট্রেকগনিজেসলেক্টর করে কল করুন: এবং সুতরাং শ্রেণিটি অকেজো করে তোলে এমন ব্যতিক্রম বাড়াতে পারেন।

উদাহরণ স্বরূপ:

- (id)someMethod:(SomeObject*)blah
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

আপনি init এর জন্যও এটি করতে পারেন।


5
@ চক, আমি নিম্নগতিতে যাই নি, তবে NSObjectরেফারেন্সটি এমনটি ব্যবহার করার পরামর্শ দেয় যেখানে আপনি কোনও পদ্ধতির উত্তরাধিকারী হতে না, কোনও পদ্ধতির ওভাররাইডিং প্রয়োগ করতে চান না। যদিও সেগুলি একই জিনিস হতে পারে, সম্ভবত :)
ড্যান রোজনস্টার্ক

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

আমি এটিকে কমানোর চেষ্টা করি নি, তবে আপনার টিআইপি পদ্ধতিতে কোনও ব্যতিক্রম উত্থাপন করার পরামর্শটি সম্ভবত এটির সবচেয়ে সম্ভবত কারণ। সাবক্লাসের সর্বাধিক সাধারণ ফর্ম্যাটটি স্ব = [সুপার থ্রি] কল করে এটির নিজস্ব আরম্ভ পদ্ধতি শুরু করবে - যা বাধ্যতার সাথে একটি ব্যতিক্রম ছুঁড়ে ফেলবে। এই ফর্ম্যাটটি বেশিরভাগ পদ্ধতির জন্য ভাল কাজ করে তবে সাবক্লাসটি এটির সুপার বাস্তবায়ন বলতে পারে এমন কোনও জায়গায় আমি কখনও এটি করব না।
Xono

5
আপনি অবজেক্ট-সি তে সম্পূর্ণ বিমূর্ত ক্লাস তৈরি করতে পারেন এবং এটি বেশ সাধারণ। অ্যাপল ফ্রেমওয়ার্কের বেশ কয়েকটি ক্লাস রয়েছে যা এটি করে। অ্যাপলের অ্যাবস্ট্রাক্ট ক্লাসগুলি নির্দিষ্ট ব্যতিক্রমগুলি (NSInuthorArgumentException) ফেলে দেয়, প্রায়শই NSInuthorAbstractInvocation () কল করে। একটি বিমূর্ত পদ্ধতি কল একটি প্রোগ্রামিং ত্রুটি, যে কারণে এটি একটি ব্যতিক্রম ছোঁড়ে। বিমূর্ত কারখানাগুলি সাধারণত ক্লাস ক্লাস্টার হিসাবে প্রয়োগ করা হয়।
জোর করে

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

60

উপরের @ ব্যারি ওয়ার্কের উত্তরের উপর কেবল রিফিং করা (এবং আইওএস ৪.৩-এর জন্য আপডেট করা) এবং এটি আমার নিজস্ব রেফারেন্সের জন্য রেখেছি:

#define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define methodNotImplemented() mustOverride()

তাহলে আপনার পদ্ধতিতে আপনি এটি ব্যবহার করতে পারেন

- (void) someMethod {
     mustOverride(); // or methodNotImplemented(), same thing
}



দ্রষ্টব্য: ম্যাক্রোটিকে সি ফাংশনের মতো দেখানো ভাল ধারণা কিনা তা নিশ্চিত নয়, তবে আমি বিপরীতভাবে এটিকে চালিত না করা পর্যন্ত রাখব। আমি মনে করি এটি ব্যবহারের NSInvalidArgumentExceptionচেয়ে আরও সঠিক ( NSInternalInconsistencyExceptionযেহেতু) যা রানটাইম সিস্টেমটি doesNotRecognizeSelectorডাকা হওয়ার প্রতিক্রিয়ায় নিক্ষেপ করেছে ( NSObjectডক্স দেখুন)।


1
নিশ্চিত কথা, টোমএ, আমি আশা করি এটি আপনাকে ম্যাক্রো করতে পারে এমন অন্যান্য কোডের জন্য ধারণা দেয়। আমার সর্বাধিক ব্যবহৃত ম্যাক্রো সিঙ্গলটনের একটি সাধারণ রেফারেন্স: কোডটি বলে universe.thingতবে এটি প্রসারিত হয় [Universe universe].thing। বড় মজা, হাজার হাজার কোডের অক্ষর সংরক্ষণ করা ...
ড্যান রোজনস্টার্ক

গ্রেট। একটু, যদিও পরিবর্তিত: #define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
noamtm

1
@ ইয়ার: আমার মনে হয় না। আমরা __PRETTY_FUNCTION__এখানে প্রস্তাবিত হিসাবে DLog (...) ম্যাক্রোর মাধ্যমে পুরো জায়গা জুড়ে ব্যবহার করি : stackoverflow.com/a/969291/38557
noamtm

1
আরও বিশদের জন্য -#define setMustOverride() NSLog(@"%@ - method not implemented", NSStringFromClass([self class])); mustOverride()
gbk

1
যদি আপনি বেস ক্লাস যুক্ত করেন এবং 10 বার উদাহরণস্বরূপ এই শ্রেণীর উত্তরাধিকারী হন এবং এক ক্লাসে এটি প্রয়োগ করতে ভুলে গিয়েছেন তবে বেস ক্লাসের নামের সাথে বার্তা পাবেন আপনার মতো উত্তরাধিকারসূত্রে প্রাপ্ত নয় Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[BaseDynamicUIViewController localizeUI] must be overridden in a subclass/category'ক্ষেত্রে আমি প্রস্তাবিত HomeViewController - method not implementedআপনিও পাবেন যেখানে হোমভিউকন্ট্রোলার বেস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত - এটি আরও তথ্য দেবে
gbk

42

আমি যে সমাধানটি নিয়ে এসেছি তা হ'ল:

  1. আপনার "বিমূর্ত" শ্রেণিতে আপনি যা চান তার জন্য একটি প্রোটোকল তৈরি করুন
  2. প্রোটোকল প্রয়োগ করে এমন একটি বেস শ্রেণি তৈরি করুন (বা সম্ভবত এটি বিমূর্ত কল করুন)। আপনি যে সমস্ত পদ্ধতির জন্য "বিমূর্ত" চান সেগুলি .m ফাইলটিতে প্রয়োগ করুন, তবে .h ফাইলটি নয় not
  3. আপনার শিশু শ্রেণিকে বেস বর্গ থেকে উত্তরাধিকারী করুন এবং প্রোটোকলটি প্রয়োগ করুন।

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

এটি জাভার মতো পারস্পরিক সংযোগ নয়, তবে আপনি পছন্দসই সংকলক সতর্কতা পান।


2
+1 এটি আসলে সমাধান যা জাভাতে একটি বিমূর্ত শ্রেণীর নিকটে আসে। আমি এই পদ্ধতির নিজেকে ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করে। এমনকি এটি প্রোটোকলটির নাম বেস ক্লাসের মতো (যেমন অ্যাপল করেছিল NSObject) নামকরণ করার অনুমতি দেওয়া হয় । আপনি যদি একই শিরোলেখ ফাইলটিতে প্রোটোকল এবং বেস শ্রেণীর ঘোষণা রাখেন তবে এটি একটি বিমূর্ত শ্রেণীর কাছ থেকে প্রায় পৃথক পৃথক।
কোডিংফ্রেন্ড 1

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

1
আপনার কেবল শিশু ক্লাসগুলি প্রোটোকলটি প্রয়োগ করতে পারে এবং সুপারক্লাস পদ্ধতিগুলি ফাঁকা পরিবর্তে একসাথে ছেড়ে যেতে পারে। তারপরে সুপারক্লাস <মাইপ্রোটোকল> টাইপের বৈশিষ্ট্য রয়েছে। এছাড়াও, যুক্ত নমনীয়তার জন্য আপনি আপনার প্রোটোকলগুলিতে @ বিকল্পের সাথে আপনার পদ্ধতিগুলি উপসর্গ করতে পারেন।
ডটটোস্ট্রিং

এটি এক্সকোড 5.0.2 তে কাজ করে না বলে মনে হয়; এটি কেবল "বিমূর্ত" শ্রেণীর জন্য একটি সতর্কতা উত্পন্ন করে। "বিমূর্ত" শ্রেণিটি প্রসারিত না করা সঠিক সংকলক সতর্কতা উত্পন্ন করে তবে স্পষ্টতই আপনাকে পদ্ধতিগুলি উত্তরাধিকার সূচিত করতে দেয় না।
তোফার ফ্যাঙ্গিও

আমি এই সমাধানটি পছন্দ করি তবে সত্যই এটি পছন্দ হয় না, এটি প্রকল্পে ভাল কোড কাঠামো নয়। // সাবক্লাসের জন্য বেস টাইপ হিসাবে এটি ব্যবহার করা উচিত। টাইপডেফ বেসক্লাস <বেসক্লাসপ্রোটোকল> বেসকলাস; এটি মাত্র এক সপ্তাহের নিয়ম, আমি এটি পছন্দ করি না।
ইটাচি

35

থেকে ওমনি গ্রুপ মেইলিং লিস্ট :

অবজেক্টিভ-সি এর কাছে জাভা এর মতো বিমূর্ত সংকলক নির্মাণ নেই।

সুতরাং আপনি যা কিছু করেন তা হ'ল বিমূর্ত শ্রেণিকে অন্য কোনও সাধারণ শ্রেণি হিসাবে সংজ্ঞায়িত করা এবং বিমূর্ত পদ্ধতিগুলির জন্য পদ্ধতিগুলি স্টাবগুলি কার্যকর করা হয় যা হয় ফাঁকা হয় বা নির্বাচককে সমর্থন না করার জন্য প্রতিবেদন করে। উদাহরণ স্বরূপ...

- (id)someMethod:(SomeObject*)blah
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

আমি ডিফল্ট প্রাথমিককরণের মাধ্যমে বিমূর্ত শ্রেণীর সূচনা রোধ করতে নিম্নলিখিতগুলিও করি।

- (id)init
{
     [self doesNotRecognizeSelector:_cmd];
     [self release];
     return nil;
}

1
আমি -desNotRecognizeSelector ব্যবহার করার কথা ভাবি নি: এবং আমি কিছু পদ্ধতিতে এই পদ্ধতির পছন্দ করি। সংকলক ইস্যু করার উপায় কি কেউ জানেন যে এইভাবে তৈরি করা হয়েছে "বিমূর্ত" পদ্ধতির জন্য বা কোনও ব্যতিক্রম উত্থাপন করে? এটি দুর্দান্ত হবে ...
কুইন টেলর

26
DoNotRecognizeSelector পদ্ধতির সাহায্যে অ্যাপল এর প্রস্তাবিত স্ব = [সুপার init] প্যাটার্নকে বাধা দেয়।
dlinsin

1
@ ডেভিড: আমি পুরোপুরি নিশ্চিত যে যত তাড়াতাড়ি সম্ভব একটি ব্যতিক্রম বাড়াতে হবে sure আদর্শভাবে এটি সংকলনের সময় হওয়া উচিত, তবে যেহেতু এটি করার কোনও উপায় নেই, তাই তারা রান টাইম ব্যতিক্রম স্থির করে। এটি দৃ failure় ব্যর্থতার অনুরূপ, যা উত্পাদন কোডে প্রথম স্থানে উত্থাপন করা উচিত নয়। প্রকৃতপক্ষে, একটি দৃsert় (মিথ্যা) আসলে আরও ভাল হতে পারে কারণ এটি পরিষ্কার যে এই কোডটি কখনই চলবে না। ব্যবহারকারী এটি ঠিক করতে কিছু করতে পারেন না, বিকাশকারীকে এটি ঠিক করতে হবে। সুতরাং এখানে একটি ব্যতিক্রম বা দৃ failure় ব্যর্থতা উত্থাপন একটি ভাল ধারণা মত শোনাচ্ছে।
সংবেদনশীল

2
আমি মনে করি না এটি এটি একটি কার্যকর সমাধান কারণ সাবক্লাসগুলির [সুপার থ্রি] তে পুরোপুরি বৈধ কল থাকতে পারে।
রাফি খ্যাচডৌড়িয়ান

@ ডলিনসিন: বিমূর্ত ক্লাসটি যখন আরআইডি-র মাধ্যমে আরম্ভ করার কথা নয় তখন আপনি ঠিক এটি চান। এর সাবক্লাসগুলি সম্ভবত সুপার পদ্ধতিটি কল করতে পারে তা জানে তবে এটি "নতুন" বা "বরাদ্দ / ইআর" এর মাধ্যমে অযত্ন প্রার্থনা বন্ধ করে দেয়।
gnasher729

21

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

- (void)performOperation:(id<Operation>)op
{
   // do something with operation
}

অপশন অপারেশন প্রোটোকল প্রয়োগকারী যে কোনও বস্তু হতে পারে।

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


আমার কাছে মনে হয় এটি যে ক্ষেত্রে আপনি বিমূর্ত শ্রেণিটি ব্যবহার করবেন সে ক্ষেত্রে যাওয়ার উপযুক্ত উপায় হিসাবে অন্ততপক্ষে যখন এটি "ইন্টারফেস" বলতে বোঝায় আসলেই (সি ++ এর মতো)। এই পদ্ধতির কোনও লুকানো ডাউনসাইড রয়েছে?
জোর করে

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

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

19

এই থ্রেডটি একধরনের পুরানো এবং আমি যা ভাগ করতে চাই তার বেশিরভাগই এখানে ইতিমধ্যে।

তবে, আমার প্রিয় পদ্ধতির উল্লেখ নেই, এবং আফাকের বর্তমান ঝাঁকুনিতে কোনও দেশীয় সমর্থন নেই, তাই আমি এখানে যাই…

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

তবে প্রদত্ত (আপনার পরিস্থিতি যত্ন সহকারে মূল্যায়ন করার পরে!) আপনি এই সিদ্ধান্তে পৌঁছে গেছেন যে প্রতিনিধিদল (বা সাধারণভাবে রচনা) আপনার সমস্যা সমাধানের পক্ষে উপযুক্ত নয়, আমি এখানে কীভাবে এটি করছি:

  1. বেস ক্লাসে প্রতিটি বিমূর্ত পদ্ধতি প্রয়োগ করুন।
  2. যে বাস্তবায়ন করুন [self doesNotRecognizeSelector:_cmd]; ...
  3. … এরপরে __builtin_unreachable();সতর্কবার্তাটি নীরব করার জন্য আপনি অ-শূন্য পদ্ধতিগুলি পেয়ে যাবেন, আপনাকে বলছেন যে "রিটার্ন ছাড়াই অ-শূন্য ফাংশনটির নিয়ন্ত্রণ পৌঁছেছে" telling
  4. হয় ম্যাক্রোতে ২ এবং ৩ পদক্ষেপ একত্রিত করুন, বা প্রয়োগের ব্যতীত কোনও বিভাগে -[NSObject doesNotRecognizeSelector:]ব্যবহার করে এনোটেট করুন যাতে সেই পদ্ধতির আসল বাস্তবায়নটি প্রতিস্থাপন না করা হয় এবং আপনার প্রকল্পের পিসিএইচটিতে সেই বিভাগের শিরোনাম অন্তর্ভুক্ত করা উচিত।__attribute__((__noreturn__))

আমি ব্যক্তিগতভাবে ম্যাক্রো সংস্করণটিকে পছন্দ করি কারণ এটি আমাকে যতটা সম্ভব বয়লারপ্লেট হ্রাস করতে দেয়।

এটা এখানে:

// Definition:
#define D12_ABSTRACT_METHOD {\
 [self doesNotRecognizeSelector:_cmd]; \
 __builtin_unreachable(); \
}

// Usage (assuming we were Apple, implementing the abstract base class NSString):
@implementation NSString

#pragma mark - Abstract Primitives
- (unichar)characterAtIndex:(NSUInteger)index D12_ABSTRACT_METHOD
- (NSUInteger)length D12_ABSTRACT_METHOD
- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange D12_ABSTRACT_METHOD

#pragma mark - Concrete Methods
- (NSString *)substringWithRange:(NSRange)aRange
{
    if (aRange.location + aRange.length >= [self length])
        [NSException raise:NSInvalidArgumentException format:@"Range %@ exceeds the length of %@ (%lu)", NSStringFromRange(aRange), [super description], (unsigned long)[self length]];

    unichar *buffer = (unichar *)malloc(aRange.length * sizeof(unichar));
    [self getCharacters:buffer range:aRange];

    return [[[NSString alloc] initWithCharactersNoCopy:buffer length:aRange.length freeWhenDone:YES] autorelease];
}
// and so forth…

@end

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

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

আমি কেন এই পদ্ধতিটি বেছে নিই

  1. এটি দক্ষতার সাথে এবং কিছুটা সুবিধাজনকভাবে কাজটি সম্পন্ন করেছে।
  2. এটি বুঝতে মোটামুটি সহজ। (ঠিক আছে, এটি __builtin_unreachable()মানুষকে অবাক করে দিতে পারে তবে এটি বোঝাও যথেষ্ট সহজ))
  3. এটি অন্য সংকলক সতর্কতা বা ত্রুটিগুলি তৈরি না করে রিলিজ বিল্ডগুলিতে ছিনিয়ে নেওয়া যায় না - দৃ one় ম্যাক্রোগুলির একটির ভিত্তিতে এমন একটি পদ্ধতির विपरीत।

এই শেষ পয়েন্টটির কিছু ব্যাখ্যা দরকার, আমার ধারণা:

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

এটি যথেষ্ট খারাপ যে আপনি এই জাতীয় প্রোগ্রামার ত্রুটির জন্য যথাযথ সংকলন-সময় ডায়াগনস্টিকগুলি অর্জন করতে পারবেন না এবং এগুলির জন্য অ্যান-রান-টাইম আবিষ্কার অবলম্বন করতে হবে, তবে যদি আপনি এটির রিলিজ তৈরি করতে পারেন তবে কেন একটি বিমূর্ত শ্রেণিতে চেষ্টা করবেন প্রথম স্থান?


এটি আমার নতুন প্রিয় সমাধান - __builtin_unreachable();মণি এই কাজটিকে নিখুঁত করে তোলে। ম্যাক্রো এটিকে স্ব-ডকুমেন্টিং করে এবং আচরণটি মেলে যদি আপনি কোনও বস্তুর গায়েবি পদ্ধতিতে কল করেন তবে কী ঘটে।
অ্যালেক্স MDC

12

ব্যবহার @propertyএবং @dynamicকাজ করতে পারে। যদি আপনি একটি গতিশীল সম্পত্তি ঘোষণা করেন এবং কোনও মিলে যাওয়া পদ্ধতি বাস্তবায়ন না দেন, তবে সতর্কতা ছাড়াই সমস্ত কিছু সঙ্কলিত হবে এবং আপনি unrecognized selectorযদি এটির অ্যাক্সেস করার চেষ্টা করেন তবে রানটাইমে একটি ত্রুটি পাবেন get এটি মূলত কল করার মতো একই জিনিস [self doesNotRecognizeSelector:_cmd], তবে টাইপ করার চেয়েও কম।


7

এক্সকোডে (ক্ল্যাং ইত্যাদি ব্যবহার করে) আমি __attribute__((unavailable(...)))বিমূর্ত ক্লাসগুলিতে ট্যাগ করতে ব্যবহার করতে চাই যাতে আপনি চেষ্টা করে ব্যবহার করেন তবে একটি ত্রুটি / সতর্কতা পান।

এটি আকস্মিকভাবে পদ্ধতিটি ব্যবহারের বিরুদ্ধে কিছুটা সুরক্ষা সরবরাহ করে।

উদাহরণ

বেস শ্রেণিতে @interfaceট্যাগ "বিমূর্ত" পদ্ধতি:

- (void)myAbstractMethod:(id)param1 __attribute__((unavailable("You should always override this")));

আরও এক ধাপ এগিয়ে নিয়ে যাওয়া, আমি একটি ম্যাক্রো তৈরি করি:

#define UnavailableMacro(msg) __attribute__((unavailable(msg)))

এটি আপনাকে এটি করতে দেয়:

- (void)myAbstractMethod:(id)param1 UnavailableMacro(@"You should always override this");

যেমনটি আমি বলেছিলাম, এটি বাস্তব সংকলক সুরক্ষা নয় তবে এটি এমন ভাষাতে যেমন আপনার বিমূর্ত পদ্ধতি সমর্থন করে না তেমনই ভাল।


1
আমি পেলাম না। আমি আমার বেস বর্গ উপর আপনার পরামর্শের প্রয়োগ -init পদ্ধতি এবং এখন Xcode আমাকে উত্তরাধিকারসূত্রে ক্লাসের একটা নিদর্শন এবং কম্পাইল সময় ত্রুটি দেখা দেয় সৃষ্টি অনুমতি দেয় না অনুপলব্ধ ... । আপনি আরও ব্যাখ্যা করতে পারেন?
অণিম

-initআপনার সাবক্লাসে আপনার কোনও পদ্ধতি রয়েছে তা নিশ্চিত করুন ।
রিচার্ড স্টিলিং

2
এটি এনএস_উইএনএইএইএইএলআইবিএল এর মতো যা আপনি যখনই এই জাতীয় বৈশিষ্ট্যের সাথে চিহ্নিত পদ্ধতিটিকে কল করার চেষ্টা করবেন ততবার ত্রুটি ঘটবে। এটি কীভাবে বিমূর্ত শ্রেণিতে ব্যবহার করা যায় তা আমি দেখছি না।
বেন সিনক্লেয়ার

7

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

বিকল্প 1: প্রোটোকল

আপনি যদি কোনও বাস্তবায়ন না করে একটি বিমূর্ত শ্রেণি তৈরি করতে চান তবে 'প্রোটোকল' ব্যবহার করুন। প্রোটোকলের উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাসগুলি প্রোটোকলটিতে পদ্ধতিগুলি প্রয়োগ করতে বাধ্য।

@protocol ProtocolName
// list of methods and properties
@end

বিকল্প 2: টেম্পলেট পদ্ধতি প্যাটার্ন

আপনি যদি "টেম্পলেট পদ্ধতি প্যাটার্ন" এর মতো আংশিক বাস্তবায়ন সহ একটি বিমূর্ত শ্রেণি তৈরি করতে চান তবে এটি সমাধান। উদ্দেশ্য-সি - টেমপ্লেটের পদ্ধতিগুলির প্যাটার্ন?


6

আরেকটি বিকল্প

কেবল অ্যাবস্ট্রাক্ট ক্লাসে ক্লাসটি পরীক্ষা করুন এবং আপনার কল্পনা করা যাই হোক না কেন দৃsert় বা ব্যতিক্রম।

@implementation Orange
- (instancetype)init
{
    self = [super init];
    NSAssert([self class] != [Orange class], @"This is an abstract class");
    if (self) {
    }
    return self;
}
@end

এটি ওভাররাইড করার প্রয়োজনীয়তা অপসারণ করে init


এটা কি শুধু শূন্য ফেরত দক্ষ হবে? অথবা এর ফলে কোনও ব্যতিক্রম / অন্য ত্রুটি নিক্ষেপ হবে?
ব্যবহারকারী 2277872

ভাল এটি কেবল ক্লাসটি সরাসরি ব্যবহারের জন্য প্রোগ্রামারদের ধরার জন্য, যা আমি মনে করি একটি দৃ of় ব্যবহারের ভাল ব্যবহার করে।
bigkm

5

(সম্পর্কিত পরামর্শ আরও)

আমি প্রোগ্রামারকে "সন্তানের কাছ থেকে কল করবেন না" এবং সম্পূর্ণরূপে ওভাররাইড করার উপায় জানাতে চাই (আমার ক্ষেত্রে এখনও প্রসারিত না হওয়ার পরে পিতামাতার পক্ষ থেকে কিছু ডিফল্ট কার্যকারিতা সরবরাহ করা হবে):

typedef void override_void;
typedef id override_id;

@implementation myBaseClass

// some limited default behavior (undesired by subclasses)
- (override_void) doSomething;
- (override_id) makeSomeObject;

// some internally required default behavior
- (void) doesSomethingImportant;

@end

সুবিধাটি হ'ল প্রোগ্রামার ঘোষণাপত্রে "ওভাররাইড" দেখতে পাবে এবং তারা জানতে পারবে না যে তাদের কল করা উচিত নয় [super ..]

মঞ্জুর, এটির জন্য স্বতন্ত্র রিটার্নের ধরনগুলি নির্ধারণ করা কুৎসিত, তবে এটি যথেষ্ট ভাল ভিজ্যুয়াল ইঙ্গিত হিসাবে কাজ করে এবং আপনি একটি সাবক্লাস সংজ্ঞাতে সহজেই "ওভাররাইড_" অংশটি ব্যবহার করতে পারবেন না।

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

এটির মতো সংকলক ইঙ্গিতগুলি তৈরি করা ভাল হবে, এমনকি কোনও মন্তব্য / ডকুমেন্টেশন বা ... ধরে নেওয়ার পরিবর্তে সুপারটির বাস্তবায়নটি প্রি / পোস্ট করা ভাল when

ইঙ্গিত উদাহরণ


4

আপনি যদি অন্য ভাষায় বিমূর্ত তদন্ত লঙ্ঘনকারী সংকলককে অভ্যস্ত করে থাকেন তবে উদ্দেশ্য-সি আচরণ হতাশাজনক।

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

এই ধরণের স্ট্যাটিক পরীক্ষার জন্য আমরা প্রাথমিকভাবে আড়াল করতে কয়েকটি কৌশল ব্যবহার করে যাচ্ছি তা এখানে:

//
//  Base.h
#define UNAVAILABLE __attribute__((unavailable("Default initializer not available.")));

@protocol MyProtocol <NSObject>
-(void) dependentFunction;
@end

@interface Base : NSObject {
    @protected
    __weak id<MyProtocol> _protocolHelper; // Weak to prevent retain cycles!
}

- (instancetype) init UNAVAILABLE; // Prevent the user from calling this
- (void) doStuffUsingDependentFunction;
@end

//
//  Base.m
#import "Base.h"

// We know that Base has a hidden initializer method.
// Declare it here for readability.
@interface Base (Private)
- (instancetype)initFromDerived;
@end

@implementation Base
- (instancetype)initFromDerived {
    // It is unlikely that this becomes incorrect, but assert
    // just in case.
    NSAssert(![self isMemberOfClass:[Base class]],
             @"To be called only from derived classes!");
    self = [super init];
    return self;
}

- (void) doStuffUsingDependentFunction {
    [_protocolHelper dependentFunction]; // Use it
}
@end

//
//  Derived.h
#import "Base.h"

@interface Derived : Base
-(instancetype) initDerived; // We cannot use init here :(
@end

//
//  Derived.m
#import "Derived.h"

// We know that Base has a hidden initializer method.
// Declare it here.
@interface Base (Private)
- (instancetype) initFromDerived;
@end

// Privately inherit protocol
@interface Derived () <MyProtocol>
@end

@implementation Derived
-(instancetype) initDerived {
    self= [super initFromDerived];
    if (self) {
        self->_protocolHelper= self;
    }
    return self;
}

// Implement the missing function
-(void)dependentFunction {
}
@end

3

সম্ভবত এই ধরণের পরিস্থিতি কেবল বিকাশের সময়েই হওয়া উচিত, সুতরাং এটি কাজ করতে পারে:

- (id)myMethodWithVar:(id)var {
   NSAssert(NO, @"You most override myMethodWithVar:");
   return nil;
}

3

আপনি @ ইয়ার দ্বারা প্রস্তাবিত একটি পদ্ধতি ব্যবহার করতে পারেন (কিছু সংশোধন সহ):

#define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define setMustOverride() NSLog(@"%@ - method not implemented", NSStringFromClass([self class])); mustOverride()

এখানে আপনি একটি বার্তা পাবেন:

<Date> ProjectName[7921:1967092] <Class where method not implemented> - method not implemented
<Date> ProjectName[7921:1967092] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[<Base class (if inherited or same if not> <Method name>] must be overridden in a subclass/category'

বা দাবি:

NSAssert(![self respondsToSelector:@selector(<MethodName>)], @"Not implemented");

এই ক্ষেত্রে আপনি পাবেন:

<Date> ProjectName[7926:1967491] *** Assertion failure in -[<Class Name> <Method name>], /Users/kirill/Documents/Projects/root/<ProjectName> Services/Classes/ViewControllers/YourClass:53

এছাড়াও আপনি প্রোটোকল এবং অন্যান্য সমাধানগুলি ব্যবহার করতে পারেন - তবে এটি অন্যতম সহজ উপায়।


2

কোকো বিমূর্ত বলে কিছু সরবরাহ করে না। আমরা একটি ক্লাসের বিমূর্ততা তৈরি করতে পারি যা কেবল রানটাইমে পরীক্ষা করা হয় এবং সংকলনের সময় এটি পরীক্ষা করা হয় না।


1

আমি সাধারণত ক্লাসে আর ডি পদ্ধতিটি অক্ষম করি যা আমি বিমূর্ত করতে চাই:

- (instancetype)__unavailable init; // This is an abstract class.

আপনি যখনই ক্লাসে ডিআর কল করবেন তখন এটি সংকলনের সময় একটি ত্রুটি তৈরি করবে। আমি তখন সমস্ত কিছুর জন্য ক্লাস পদ্ধতি ব্যবহার করি।

অবজেক্টিভ সি এর বিমূর্ত ক্লাসগুলি ঘোষণার জন্য কোনও অন্তর্নির্মিত উপায় নেই।


কিন্তু আমি যখন বিমূর্ত শ্রেণীর উত্পন্ন ক্লাস থেকে [সুপার init] কল করি তখন আমি ত্রুটি পাচ্ছি। কীভাবে সমাধান করবেন?
সাহিল দোশি

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

হ্যাঁ, আমি এটা বুঝতে পেরেছি। তবে আপনার সমাধানটি সিঙ্গলটন ক্লাসের মতো এমন কিছু তৈরি করতে সহায়তা করবে যেখানে আমরা কারও ইআরডি কল করতে চাই না। আমার জ্ঞান অনুসারে বিমূর্ত শ্রেণির ক্ষেত্রে কিছু শ্রেণি এটির উত্তরাধিকারী হতে চলেছে। অন্য কি বিমূর্ত ক্লাস ব্যবহার।
সাহিল দোশি

0

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

  1. বেস (বিমূর্ত) শ্রেণিতে সংজ্ঞায়িত হওয়ার কোনও অর্থ নেই এমন সমস্ত পদ্ধতির জন্য একটি প্রোটোকল তৈরি করুন অর্থাৎ তাদের বাচ্চাদের নির্দিষ্ট প্রয়োগকরণ প্রয়োজন need
  2. যে একটি বেস (বিমূর্ত) বর্গ তৈরি করুন না এই প্রোটোকলটি প্রয়োগ । আপনি এই শ্রেণিতে অন্য কোনও পদ্ধতি যুক্ত করতে পারেন যা সাধারণ প্রয়োগ বাস্তবায়নের জন্য বোঝায়।
  3. আপনার প্রকল্পের সর্বত্র, যদি কোনও শিশু থেকে AbstractClassকোনও পদ্ধতিতে ইনপুট বা আউটপুট হতে হয় তবে AbstractClass<Protocol>পরিবর্তে এটিকে টাইপ করুন।

যেহেতু AbstractClassবাস্তবায়ন হয় না Protocol, AbstractClass<Protocol>সাবক্ল্যাসিংয়ের মাধ্যমে উদাহরণের একমাত্র উপায় । AbstractClassএকা যেমন প্রকল্পের কোথাও ব্যবহার করা যায় না, এটি বিমূর্ত হয়ে ওঠে।

অবশ্যই, এটি অবিচলিত বিকাশকারীদের কেবলমাত্র উল্লেখ করে নতুন পদ্ধতি যুক্ত করা থেকে বিরত রাখে না AbstractClass, যা শেষ পর্যন্ত (আর নয়) বিমূর্ত শ্রেণির উদাহরণ দেয়।

বাস্তব বিশ্বের উদাহরণ: আইজিলিস্টকিটের একটি বেস ক্লাস রয়েছে IGListSectionControllerযা প্রোটোকল বাস্তবায়ন করে না IGListSectionType, তবে প্রতিটি পদ্ধতির জন্য যে শ্রেণীর উদাহরণ প্রয়োজন, প্রকৃতপক্ষে টাইপটির জন্য জিজ্ঞাসা করে IGListSectionController<IGListSectionType>। সুতরাং IGListSectionControllerতাদের কাঠামোতে দরকারী কোনও কিছুর জন্য কোনও ধরণের অবজেক্ট ব্যবহার করার উপায় নেই ।


0

আসলে, অবজেক্টিভ-সিতে বিমূর্ত শ্রেণি নেই তবে আপনি একই প্রভাব অর্জন করতে প্রোটোকল ব্যবহার করতে পারেন । নমুনাটি এখানে:

CustomProtocol.h

#import <Foundation/Foundation.h>

@protocol CustomProtocol <NSObject>
@required
- (void)methodA;
@optional
- (void)methodB;
@end

TestProtocol.h

#import <Foundation/Foundation.h>
#import "CustomProtocol.h"

@interface TestProtocol : NSObject <CustomProtocol>

@end

TestProtocol.m

#import "TestProtocol.h"

@implementation TestProtocol

- (void)methodA
{
  NSLog(@"methodA...");
}

- (void)methodB
{
  NSLog(@"methodB...");
}
@end

0

বিমূর্ত শ্রেণি তৈরির একটি সাধারণ উদাহরণ

// Declare a protocol
@protocol AbcProtocol <NSObject>

-(void)fnOne;
-(void)fnTwo;

@optional

-(void)fnThree;

@end

// Abstract class
@interface AbstractAbc : NSObject<AbcProtocol>

@end

@implementation AbstractAbc

-(id)init{
    self = [super init];
    if (self) {
    }
    return self;
}

-(void)fnOne{
// Code
}

-(void)fnTwo{
// Code
}

@end

// Implementation class
@interface ImpAbc : AbstractAbc

@end

@implementation ImpAbc

-(id)init{
    self = [super init];
    if (self) {
    }
    return self;
}

// You may override it    
-(void)fnOne{
// Code
}
// You may override it
-(void)fnTwo{
// Code
}

-(void)fnThree{
// Code
}

@end

-3

আপনি কি কেবল একটি প্রতিনিধি তৈরি করতে পারবেন না?

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

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

এটি আমার কাছে বিমূর্ত বেস ক্লাসের মতো শোনাচ্ছে।

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