ฉันสามารถใช้หมวดหมู่คลาสเพื่อแทนที่เมธอดที่ใช้อยู่แล้วโดยใช้หมวดหมู่ได้หรือไม่ แบบนี้:
1) วิธีการเดิม
-(BOOL) method {
return true;
}
2) วิธีการแทนที่
-(BOOL) method {
NSLog(@"error?");
return true;
}
จะได้ผลหรือผิดกฎหมาย?
ฉันสามารถใช้หมวดหมู่คลาสเพื่อแทนที่เมธอดที่ใช้อยู่แล้วโดยใช้หมวดหมู่ได้หรือไม่ แบบนี้:
1) วิธีการเดิม
-(BOOL) method {
return true;
}
2) วิธีการแทนที่
-(BOOL) method {
NSLog(@"error?");
return true;
}
จะได้ผลหรือผิดกฎหมาย?
คำตอบ:
จากเอกสารของ Apple :
แม้ว่าภาษา Objective-C ในขณะนี้ช่วยให้คุณใช้หมวดหมู่เพื่อแทนที่วิธีการสืบทอดชั้นเรียนหรือวิธีการแม้จะมีการประกาศในอินเตอร์เฟซชั้นเรียนคุณกำลังหมดแรงจากการทำเช่นนั้น หมวดหมู่ไม่ได้ใช้แทนคลาสย่อย มีข้อบกพร่องที่สำคัญหลายประการในการใช้หมวดหมู่เพื่อแทนที่วิธีการ:
เมื่อหมวดหมู่แทนที่วิธีการที่สืบทอดมาเมธอดในหมวดหมู่สามารถเรียกใช้การใช้งานที่สืบทอดผ่านข้อความถึง
super
ได้ตามปกติ อย่างไรก็ตามหากหมวดหมู่แทนที่วิธีการที่มีอยู่ในคลาสของหมวดหมู่จะไม่มีวิธีใดที่จะเรียกใช้การใช้งานดั้งเดิมได้หมวดหมู่ไม่สามารถแทนที่เมธอดที่ประกาศในหมวดหมู่อื่นของคลาสเดียวกันได้อย่างน่าเชื่อถือ
ปัญหานี้มีความสำคัญเป็นพิเศษเนื่องจากคลาส Cocoa จำนวนมากถูกนำไปใช้โดยใช้หมวดหมู่ วิธีการที่กำหนดกรอบงานที่คุณพยายามลบล้างอาจถูกนำไปใช้ในหมวดหมู่หนึ่งและไม่ได้กำหนดการใช้งานที่มีความสำคัญ
การมีอยู่ของเมธอดหมวดหมู่บางอย่างอาจทำให้เกิดการเปลี่ยนแปลงพฤติกรรมในทุกเฟรมเวิร์ก ตัวอย่างเช่นหากคุณแทนที่
windowWillClose:
วิธีการมอบหมายในหมวดหมู่บน NSObject ผู้รับมอบสิทธิ์หน้าต่างทั้งหมดในโปรแกรมของคุณจะตอบสนองโดยใช้วิธีการประเภท พฤติกรรมของอินสแตนซ์ NSWindow ทั้งหมดของคุณอาจเปลี่ยนไป หมวดหมู่ที่คุณเพิ่มในคลาสของเฟรมเวิร์กอาจทำให้เกิดการเปลี่ยนแปลงพฤติกรรมอย่างลึกลับและนำไปสู่ข้อขัดข้อง
คุณสามารถทำได้โดยการปรับแนวทางคลัสเตอร์คลาสหรือใช้เทคนิคswizzling วิธีการ
มิฉะนั้นพฤติกรรมของทั้งสองหรือมากกว่าแบ่งวิธีการจะไม่ได้กำหนด
ลิงก์เอกสารเก่าหมดแล้ว สิ่งทดแทนที่ดีที่สุดที่ฉันสามารถหาได้คือที่นี่: Apple Docs :
หลีกเลี่ยงการปะทะกันของชื่อวิธีหมวดหมู่
เนื่องจากเมธอดที่ประกาศในหมวดหมู่จะถูกเพิ่มลงในคลาสที่มีอยู่คุณจึงต้องระมัดระวังเกี่ยวกับชื่อเมธอดให้มาก
หากชื่อของเมธอดที่ประกาศในหมวดหมู่นั้นเหมือนกับเมธอดในคลาสดั้งเดิมหรือเมธอดในหมวดหมู่อื่นในคลาสเดียวกัน (หรือแม้แต่ซูเปอร์คลาส) พฤติกรรมจะไม่ได้กำหนดว่าจะใช้เมธอดใดที่ รันไทม์ สิ่งนี้มีโอกาสน้อยที่จะเป็นปัญหาหากคุณใช้หมวดหมู่กับชั้นเรียนของคุณเอง แต่อาจทำให้เกิดปัญหาเมื่อใช้หมวดหมู่เพื่อเพิ่มวิธีการในคลาส Cocoa หรือ Cocoa Touch มาตรฐาน
มันคือ Apple ที่ใช้การสัมผัสที่เบากว่า แต่ประเด็นหลักเหมือนกันนั่นคือคุณเชิญหายนะเพราะพฤติกรรมที่คาดเดาไม่ได้นั้นเงียบ
สิ่งสำคัญคือต้องทราบว่าหมวดหมู่ยังสามารถใช้เพื่อแทนที่เมธอดที่มีอยู่ในคลาสพื้นฐานได้ (เช่นวิธีการขับเคลื่อนของคลาสรถยนต์) แต่คุณไม่ควรทำเช่นนี้ ปัญหาคือหมวดหมู่เป็นโครงสร้างองค์กรที่เรียบ หากคุณลบล้างวิธีการที่มีอยู่ใน Car + Maintenance.m แล้วตัดสินใจว่าคุณต้องการเปลี่ยนพฤติกรรมอีกครั้งด้วยหมวดหมู่อื่นไม่มีทางที่ Objective-C จะทราบว่าจะใช้การนำไปใช้งานใด การคลาสย่อยมักจะเป็นตัวเลือกที่ดีกว่าในสถานการณ์เช่นนี้
จากบทช่วยสอนนี้http://rypress.com/tutorials/objective-c/categories