วิธีการโอเวอร์โหลดใน Objective-C?


131

เท่าที่ฉันรู้ Objective-C ไม่สนับสนุนวิธีการโอเวอร์โหลด อะไรคือทางเลือกอื่นสำหรับสิ่งนี้ใน Objective-C? หรือฉันควรใช้ชื่อวิธีการอื่นเสมอ?

คำตอบ:


193

ถูกต้องวัตถุประสงค์ -C ไม่สนับสนุนวิธีการโอเวอร์โหลดดังนั้นคุณต้องใช้ชื่อเมธอดอื่น

อย่างไรก็ตามโปรดทราบว่า "ชื่อเมธอด" มีคีย์เวิร์ดลายเซ็นเมธอด (ชื่อพารามิเตอร์ที่อยู่ก่อน ":" s) ดังนั้นต่อไปนี้จึงเป็นสองวิธีที่แตกต่างกันแม้ว่าทั้งคู่จะขึ้นต้น "writeToFile":

-(void) writeToFile:(NSString *)path fromInt:(int)anInt;
-(void) writeToFile:(NSString *)path fromString:(NSString *)aString;

(ชื่อของสองวิธีคือ "writeToFile: fromInt:" และ "writeToFile: fromString:")


4
@RaheelSadiq มันไม่โอเวอร์โหลดเพราะชื่อเมธอด (ใน ObjC: 'selectors') แตกต่างกัน ความแตกต่างไม่มีใครถูกมองว่า 'โอเวอร์โหลด' หากมีการกำหนด writeToFile: from: สองครั้งโดยมีเพียงประเภทพารามิเตอร์เท่านั้นที่แตกต่างกันนั่นจะเป็นการโอเวอร์โหลด ตามที่ระบุไว้ว่าสิ่งนี้ไม่ได้รับการสนับสนุนใน ObjC เหมือนกับภาษาอื่น ๆ รวมถึง Java และตอนนี้ Swift
Chris Hatton

ไม่ใช่แค่พารามิเตอร์ตั้งชื่อเอง แต่แม้แต่โคลอนก็เป็นส่วนหนึ่งของชื่อเมธอดดังนั้น - (โมฆะ) writeToFile: (NSString *) พา ธ : (int) anInt; และ - (โมฆะ) writeToFile: (NSString ) พา ธ : (NSString ) aString เป็นวิธีการที่แตกต่างกัน
Kaiserludi

22

อาจเป็นเรื่องที่ควรค่าแก่การกล่าวถึงว่าแม้ว่า Objective-C จะไม่รองรับวิธีการโอเวอร์โหลด แต่ Clang + LLVM ก็รองรับการทำงานมากเกินไปสำหรับ C แม้ว่าจะไม่ใช่สิ่งที่คุณกำลังมองหา แต่ก็สามารถพิสูจน์ได้ว่ามีประโยชน์ในบางสถานการณ์ (ตัวอย่างเช่นเมื่อ การดำเนินการhacked เล็กน้อย (ไปกับการห่อหุ้ม) เวอร์ชั่นของรูปแบบการออกแบบของผู้เข้าชม )

นี่คือตัวอย่างง่ายๆเกี่ยวกับการทำงานของฟังก์ชันที่โอเวอร์โหลด:

__attribute__((overloadable)) float area(Circle * this)
{
    return M_PI*this.radius*this.radius;
}

__attribute__((overloadable)) float area(Rectangle * this)
{
    return this.w*this.h;
}

//...
//In your Obj-C methods you can call:
NSLog(@"%f %f", area(rect), area(circle));

ใครจะคิดว่าคำใบ้นี้เมื่อรวมกับวิธีการที่สลับไปมาอาจนำไปสู่วิธีการที่ "โอเวอร์โหลด" ได้อย่างแท้จริง ... ทำไมต้องมีidและisKindOfClass:ในการกำจัดแม้ว่าจะเป็นคนละเรื่อง ...
Alex Gray

1
@alexgray ฉันเห็นประเด็นของคุณ idและisKindOfClass:ครอบคลุมสถานการณ์ที่เป็นประโยชน์มากที่สุด เหตุผลหนึ่งที่คุณอาจชอบใช้งานมากเกินไปคือการเลือกประเภทที่เฉพาะเจาะจงที่สุดโดยอัตโนมัติซึ่งจะมีค่าใช้จ่ายเล็กน้อยในการดูแลรักษาด้วยการตรวจสอบประเภทที่ชัดเจน
Chris Hatton

1
เอกสารประกอบเสียงดังกล่าวอย่างชัดเจนว่าสิ่งที่ทำคือการให้ชื่อ C ++ สำหรับ C และนั่นเป็นเพียงคอมไพเลอร์ที่ทำเบื้องหลังโดยอัตโนมัติสิ่งที่ทำใน Objective-C โดยตั้งชื่อเมธอดที่แตกต่างกันโดยการรวม (ในรูปแบบที่ยาวขึ้น) ประเภทอาร์กิวเมนต์
Chris Stratton

19

David ถูกต้องในวิธีการที่ไม่รองรับการโอเวอร์โหลดใน Objective-C มันคล้ายกับ PHP ในแง่นั้น ในขณะที่เขายังชี้ให้เห็นเป็นเรื่องปกติที่จะกำหนดวิธีการสองวิธีขึ้นไปด้วยลายเซ็นที่แตกต่างกันในลักษณะที่เขายกตัวอย่าง อย่างไรก็ตามยังสามารถสร้างวิธีการหนึ่งโดยใช้ประเภท "id" ผ่านประเภท "id" คุณสามารถส่งออบเจ็กต์ใด ๆ (และดั้งเดิมใด ๆ โดยใช้คลาส NSNumber) ไปยังเมธอดจากนั้นจากภายในเมธอดคุณสามารถทดสอบประเภทของมันและโยนข้อยกเว้นที่เหมาะสมได้หากจำเป็น แม้ว่าสิ่งนี้จะมีผลการดำเนินงานเล็กน้อย แต่ก็มักจะเป็นเพียงเล็กน้อยหรือไม่มีนัยสำคัญเว้นแต่คุณจะประมวลผลข้อมูลจำนวนมาก

- (void) writeToFile: (NSString *)path fromObject: (id)object {
    if (!([object isKindOfClass: [NSNumber class]] || [object isKindOfClass: [NSString class]])) {
         @throw [NSException exceptionWithName: @"InvalidArgumentException" reason: @"Unrecognized parameter type." userInfo: nil];
    }
}

นอกจากนี้ยังเป็นสถานที่ที่สวยงามในการใช้โปรโตคอลเพื่อบังคับใช้ประเภทวัตถุซึ่งสามารถทำได้ดังนี้:

(id<MyProtocol>)object
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.