การเรียนรู้ Objective-C และการอ่านโค้ดตัวอย่างฉันสังเกตว่ามักจะสร้างวัตถุโดยใช้วิธีนี้:
SomeObject *myObject = [[SomeObject alloc] init];
แทน:
SomeObject *myObject = [SomeObject new];
มีเหตุผลสำหรับสิ่งนี้เพราะฉันได้อ่านว่าพวกเขาจะเทียบเท่า?
การเรียนรู้ Objective-C และการอ่านโค้ดตัวอย่างฉันสังเกตว่ามักจะสร้างวัตถุโดยใช้วิธีนี้:
SomeObject *myObject = [[SomeObject alloc] init];
แทน:
SomeObject *myObject = [SomeObject new];
มีเหตุผลสำหรับสิ่งนี้เพราะฉันได้อ่านว่าพวกเขาจะเทียบเท่า?
คำตอบ:
มีเหตุผลมากมายที่นี่: http://macresearch.org/difference-between-alloc-init-and-new
บางคนเลือกคือ:
new
ไม่รองรับ initializers ที่กำหนดเอง (เช่นinitWithString
)alloc-init
ชัดเจนกว่า new
ความคิดเห็นทั่วไปดูเหมือนว่าคุณควรใช้สิ่งที่คุณพอใจ
+newWithString:
-initWithString
ไม่ว่ากันทั่วไปว่า โดยส่วนตัวฉันมักจะใช้new
เมื่อเครื่องมือกำหนดค่าเริ่มต้นเป็นinit
เพียงแค่สั้นและหวาน
+newWithString:
ดำเนินการ นั่นเป็นการแยกความกังวลออกจากกัน เพราะเมื่อคุณเพียงต้องการที่จะใช้-init
แล้วมีเหตุผลที่จะไม่ใช้เพียง+new
แต่
[[NSString alloc] initWithFormat:...]
และ[NSString stringWithFormat:...]
มีความเท่าเทียมกัน คุณกำลังบอกว่า Apple ละเมิดการแยกข้อกังวลและไม่ควรใช้วิธีนี้ (หมายเหตุ: ฉันไม่ได้พยายามที่จะวางตัว; ฉันแค่อยากจะได้รับข้อมูลเพิ่มเติมและรู้ว่าต่อไปนี้นำไปสู่แอปเปิ้ลเป็นความคิดที่ไม่ดี)
คำถามเก่ามาก แต่ฉันได้เขียนตัวอย่างเพื่อความสนุกสนานบางทีคุณอาจพบว่ามันมีประโยชน์;)
#import "InitAllocNewTest.h"
@implementation InitAllocNewTest
+(id)alloc{
NSLog(@"Allocating...");
return [super alloc];
}
-(id)init{
NSLog(@"Initializing...");
return [super init];
}
@end
ในฟังก์ชั่นหลักทั้งสองคำสั่ง:
[[InitAllocNewTest alloc] init];
และ
[InitAllocNewTest new];
ส่งผลให้ผลลัพธ์เดียวกัน:
2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating... 2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...
[[InitAllocNewTest alloc] init]
จะไม่รวบรวมในขณะที่[InitAllocNewTest new]
ไม่ได้รับผลกระทบ (ขอโทษสำหรับการขาดตัวแบ่งบรรทัด ฯลฯ )
+new
เทียบเท่ากับการนำไปใช้+alloc/-init
ของ Apple NSObject
มันไม่น่าเป็นไปได้สูงที่สิ่งนี้จะเปลี่ยนแปลง แต่ขึ้นอยู่กับระดับความหวาดระแวงของคุณเอกสารของ Apple สำหรับ+new
ปรากฏขึ้นเพื่อให้สามารถเปลี่ยนการใช้งาน (และทำลายความเท่าเทียมกัน) ในอนาคต ด้วยเหตุนี้เพราะ "อย่างชัดเจนจะดีกว่านัย" และเพื่อความต่อเนื่องทางประวัติศาสตร์ชุมชน Objective-C +new
โดยทั่วไปหลีกเลี่ยง อย่างไรก็ตามคุณสามารถมักจะจุด comers Java ที่ผ่านมาเพื่อวัตถุประสงค์-C +new
โดยใช้พากเพียรของพวกเขา
+new
มีมาตั้งแต่ NeXT วัน หากมีสิ่งใด+new
เป็นเครื่องหมายของคนที่เรียนรู้ objc มานานแล้ว ฉันเห็นผู้คนจำนวนมากที่เพิ่งเริ่มใช้ภาษาใหม่หรือผู้ที่เคยเขียนมันมานานหลายปี แต่ชัดเจนหลังจากยุคเฟื่องฟูของ iOS ไม่มีความ+new
หมายว่าอะไร อย่างที่สอง+new
ก็คือเก่ามากและจากวัน NeXT, Apple จะค่อนข้างบ้าที่จะเปลี่ยนมันในทางที่ทำลายรหัสเก่าโดยเฉพาะอย่างยิ่งเมื่อพิจารณาจากฐานรหัสของตัวเองอาจจะทิ้งกระจุยกระจายไป
new
สำนวนนี้มาจาก Smalltalk มันยังใช้ใน Ruby และทั้ง Objective-C และ Ruby นั้นมีไวยากรณ์และแบบแผนมากมายจาก Smalltalk
บ่อยครั้งที่คุณจะต้องผ่านข้อโต้แย้งinit
และอื่น ๆ [[SomeObject alloc] initWithString: @"Foo"]
ที่คุณจะใช้วิธีการที่แตกต่างกันเช่น หากคุณกำลังใช้ในการเขียนนี้คุณจะได้รับในนิสัยของการทำวิธีนี้และอื่น ๆอาจจะมาขึ้นตามธรรมชาติที่[[SomeObject alloc] init]
[SomeObject new]
หนึ่งคำตอบสั้น ๆ คือ:
สำหรับบันทึกย่อด้านข้างฉันใช้เป็นการส่วนตัว[Foo new]
หากฉันต้องการให้บางสิ่งบางอย่างใน init ทำโดยไม่ใช้ค่าส่งคืนทุกที่ หากคุณไม่ได้ใช้การส่งคืนของ[[Foo alloc] init]
ที่ใดก็ตามคุณจะได้รับคำเตือน มากหรือน้อยฉันใช้[Foo new]
ทำอาหารตา
ฉันมาสายนี้มาก แต่ฉันต้องการพูดถึงว่าใหม่ไม่ปลอดภัยใน Obj-C กับโลก Swift Swift จะสร้างวิธีการเริ่มต้นเท่านั้นหากคุณไม่ได้สร้างเครื่องมือเริ่มต้นอื่น ๆ การเรียกสิ่งใหม่ในคลาสที่รวดเร็วด้วย initializer แบบกำหนดเองจะทำให้เกิดความผิดพลาด ถ้าคุณใช้ alloc / init คอมไพเลอร์จะบ่นว่าไม่มีอยู่
หากใหม่ทำงานให้คุณแล้วมันจะทำให้โค้ดของคุณเล็กลงเช่นกัน หากคุณจะโทร[[SomeClass alloc] init]
ในหลาย ๆ ที่ในรหัสของคุณคุณจะสร้าง Hot Spot ในการนำไปใช้งานใหม่นั่นคือใน objc runtime ซึ่งจะช่วยลดจำนวนแคชที่คุณพลาดไป
ในความเข้าใจของฉันหากคุณจำเป็นต้องใช้ initializer แบบกำหนดเอง [[SomeClass alloc] initCustom]
ในความเข้าใจของผมถ้าคุณจำเป็นต้องใช้ที่กำหนดเองการเริ่มต้นใช้งาน
[SomeClass new]
หากคุณไม่ได้ใช้
init
ฟังก์ชั่นเริ่มต้นและใช้งาน[[SomeClass alloc] init];
หากคุณต้องการพารามิเตอร์ แต่ก็ไม่เคยทำสิ่งนั้น[[SomeClass alloc] initWith:...];
เลย สุดท้ายถ้าคุณแทนที่init
ฟังก์ชั่นด้วยการใช้งานที่กำหนดเองคุณสามารถโทรหาnew
เมื่อสร้างวัตถุและมันจะยังคงเรียกการinit
ใช้งานที่กำหนดเอง