لماذا يتم تخصيص التخصيص وبدء بشكل منفصل في الهدف-C؟

StackOverflow https://stackoverflow.com/questions/1385410

سؤال

ملاحظة: أنا جديد نسبيًا على الهدف-C وأنا قادم من Java و PHP.

هل يمكن لأحد أن يشرح لي لماذا يجب عليّ دائمًا تخصيص مثيل ثم تهيئته؟

لا يمكن القيام بذلك في أساليب init مثل هذا:

+ (MyClass*)init {
    MyClass *instance = [MyClass alloc];
    [instance setFoo:@"bla"];

    return instance;
}

+ (MyClass*)initWithString:(NSString*)text {
    MyClass *instance = [MyClass init];
    [instance setFoo:text];

    return instance;
}
...

هل هذا مجرد آثار من الأيام C القديمة أم أن هناك شيء لا أراه؟

أعلم أن هذه ليست مشكلة لأنني استطعت دائمًا استدعاء TILOC و Init ، ولكن نظرًا لأنه من الممل بعض الشيء ، أود أن أعرف على الأقل سبب قيامي بذلك.

أنا أحب التعبير عن اللغة حتى الآن ، لكن هذا شيء أريد أن أفهمه تمامًا من أجل التفكير في طريقة الهدف-C.

شكرًا لك!

هل كانت مفيدة؟

المحلول

+نهايات جديدة في إرسال رسالة +تخصيص إلى الفصل ورسالة -Init إلى كل ما يعود من +inloc.

السبب في أن بعد ذلك قد غادر من اتفاقية Stepstone لاستخدام الرسالة الجديدة (التي كانت فكرة صغيرة) هو أنه في وقت مبكر ، واجهوا مواقف حيث أرادوا أن يكونوا قادرين على تهيئة نفس الكائن أكثر من مرة.

نصائح أخرى

لأن إنشاء مثيل وتهيئة مثيل هما وظيفتان منفصلتان.

أنت ترسل alloc رسالة إلى الفصل للحصول على مثيل غير ضروري. يجب عليك بعد ذلك تهيئة المثيل ، وغالبًا ما يكون لديك عدة طرق للقيام بذلك. علي سبيل المثال:

myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:@"%@.%@", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];

كل من هذه تهيئة السلسلة بطريقة مختلفة تماما. تعتمد كيفية تهيئة السلسلة على ما تريد تهيئته منه.

بالطبع ، لا أحد يحب الكتابة alloc وثم init وثم autorelease في كل مرة ، لذلك عادة ما يكون لديك طرق الراحة (على سبيل المثال ، stringWithFormat:) التي تفعل كل الخطوات الثلاث لك.

تحرير: لمعرفة المزيد حول هذا الموضوع ، بما في ذلك الأفكار الأساسية من المعلقين ، راجع منشور مدونتي "لم شمل”.

يرى NSZone.

+alloc هو مختصرة ل +allocWithZone:, ، وهي آلية توفر الكاكاو لتحسين تخصيص الذاكرة.

لذلك لديك خيار للقيام بشيء مثل هذا:

foo = [[NSString allocWithZone:MyZone] initWithString:@"Foo"];
foo2 = [foo copyWithZone:MyZone];

تتمثل الفكرة وراء مناطق الذاكرة في أنه إذا كان لديك عدد كبير من الكائنات المماثلة التي يتم تخصيصها بشكل متكرر وتخصيصها ، فقد تكون أكثر كفاءة في استخدام منطقة ذاكرة منفصلة لتلك الكائنات.

لكي تكون تقسيم المناطق فعالة تريد الحصول عليها +allocWithZone: متاح لكل فئة فرعية NSOBject ، وبالتالي تحتاج إلى فصل التخصيص والتهيئة. يمكنك إنشاء واستخدام جميع الاختصارات التي تريدها ، مثل +new, ، ولكن تحته كل ما تحتاجه -init الطريقة التي تهيئة كائن تم تخصيصه بالفعل.

"إن فصل مراحل التخصيص والتهيئة لإنشاء المثيل يوفر العديد من الفوائد. من الممكن استخدام أي اختلاف في طريقة فئة +ONIC لتخصيص مثيل ثم استخدام أي تهيئ طرق دون الحاجة إلى توفير تطبيقات بديلة لجميع طرق التخصيص. نادراً ما يتم إنشاء طرق تخصيص جديدة لأن الأساليب الحالية تلبي كل احتياجات تقريبًا. ، يجب على تطبيقات التهيئة التعامل فقط مع متغيرات الحالات الجديدة ويمكن أن تتجاهل تمامًا القضايا المخصصة للتخصيص. الفصل يبسط عملية كتابة المهيئات. على سبيل المثال تم تخصيصها. نتيجة سلبية واحدة إن فصل التخصيص والتهيئة هو الحاجة إلى أن تكون على دراية بالاتفاقيات مثل المهيمنة المحددة. يجب أن تعرف الطرق المهيمنة المعينة وكيفية إنشاء وتوثيق المهيئات الجديدة في الفئات الفرعية. على المدى الطويل ، يؤدي استخدام المهيئات المعينة إلى تبسيط تطوير البرمجيات ، ولكن هناك حجة يجب تقديمها إلى أن نمط إنشاء المرحلة Thetwo يضيف إلى منحنى التعلم المبكر لمطوري الكاكاو. "


(ج) أنماط تصميم الكاكاو بقلم إريك م. باك ودونالد أ. ياكتمان

ليس عليك ذلك. يمكنك استخدام [MyClass new]. هذا يشبه الافتراضي الخاص بك init طريقة.

في الأساس ، يفصل الهدف-C ، الذي لم يكن لديه جمع القمامة في البداية ، مفهوم تخصيص الذاكرة وتهيئة الفصل. لهذا السبب هناك طريقتان متميزتان. عندما تتصل alloc, ، أنت تخصيص الذاكرة بشكل صريح.

معظم الفصول لديها ما تطلبه. لقد حصلت على إجابات من قبل حول سبب هذا الأمر ولماذا لا ترغب دائمًا في استخدام هذا طوال الوقت ، ولكن إذا قرأت الوثائق على الفصول الدراسية ، فسترى العديد من أساليب الفصل التي تتصرف بهذه الطريقة وغالبًا ما يتم استخدامها.

من أجل NSString لديك ، على سبيل المثال:

+ (id)string  // (Empty string)
+ (id)stringWithFormat:...  // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL

وهلم جرا. ثم تستخدم هذا مثل: NSString *myString = [NSString stringWithFormat:@"Hello %@\n", userName];

معظم الفصول الأخرى لديها هذا ، مثل nsarray:

+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...

تحتاج فقط إلى قراءة الوثائق. :) وقراءة الردود الأخرى حول سبب عدم رغبة هذا الأمر كثيرًا.

تخصيص : يتم تخصيص الذاكرة/مُعطى إلى مرجع الكائن. الآن المرجع لديه حيازة الذاكرة ولكن لم يفعل أي شيء بعد. تكون هذه الذاكرة فارغة (ندرة في حالة) أو مع بعض البيانات المجهولة.

تخصيص ويبت : يتم تنظيف/إفراغ الذاكرة المخصصة. يتم بدء الذاكرة عن طريق الصفر.

تخصيص و initwithdata ... : يتم بدء الذاكرة المخصصة مع البيانات المطلوبة المحترمة لخصائص الفصل.

على سبيل المثال عند شراء مؤامرة تحصل على الحيازة. يتم إعطاء هذه المؤامرة لك كما هي ، قد يكون هناك الطوب المدمر أو المنزل القديم. هذا هو تخصيص.

عندما تقوم بتنظيف مؤامرةك وإزالة كل الأوساخ والقمامة. هذا هو تخصيص مع init.

عندما تقوم ببناء ذلك في منزل قيم ، يصبح الأمر أكثر فائدة لك. و هو تخصيص initwith ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top