ความแตกต่างระหว่าง Category และ Class Extension?


85

อะไรคือความแตกต่างระหว่างหมวดหมู่และส่วนขยายคลาส ฉันเชื่อว่าทั้งสองใช้เพื่อเพิ่มวิธีการที่กำหนดเองในคลาสที่มีอยู่ ใครบางคนสามารถให้ความสำคัญกับเรื่องนี้ได้หรือไม่? การตรวจสอบด้วยรหัสจะได้รับการชื่นชมอย่างมาก



3
ไม่พบหน้า Akusete
Adil Hussain

มีภาพประกอบชัดเจนcode.tutsplus.com/tutorials/…
grassyburrito

คำตอบ:


103

หมวดหมู่คือวิธีการเพิ่มเมธอดในคลาสที่มีอยู่ โดยปกติจะอยู่ในไฟล์ที่เรียกว่า "Class + CategoryName.h" เช่น "NSView + CustomAdditions.h" (และ. m แน่นอน)

ส่วนขยายคลาสเป็นหมวดหมู่ยกเว้นความแตกต่างหลัก 2 ประการ:

  1. หมวดหมู่ไม่มีชื่อ มีการประกาศดังนี้:

    @ อินเทอร์เฟซ SomeClass ()
    
    
    - (void) anAdditionalMethod;
    
    @end
  2. การนำส่วนขยายไปใช้งานต้องอยู่ในบล็อก @implementation หลักของไฟล์

เป็นเรื่องปกติที่จะเห็นส่วนขยายคลาสที่ด้านบนของไฟล์. m ที่ประกาศวิธีการเพิ่มเติมในคลาสซึ่งจะถูกนำไปใช้ด้านล่างในส่วน @implementation หลักของคลาส นี่เป็นวิธีประกาศเมธอด "หลอกส่วนตัว" (หลอกส่วนตัวเพราะไม่ได้เป็นส่วนตัวจริง ๆ ไม่ใช่แค่เปิดเผยภายนอก)


13
ใน Class-Extensiosn คุณสามารถเขียนทับคุณสมบัติจากคุณสมบัติแบบอ่านอย่างเดียว (สาธารณะ) เพื่อให้อ่านภายในได้ และเนื่องจาก LLVM 1.5 คุณสามารถทำอะไรได้มากกว่านี้: ตอนนี้คุณสามารถประกาศตัวแปรอินสแตนซ์ในส่วนขยายคลาสได้ดังนั้นพวกมันจึงหายไปจากอินเทอร์เฟซปกติ
Max Seelemann

ทำไมต้องเพิ่มส่วนขยายคลาสในเมื่อคุณสามารถใช้เมธอดและคุณสมบัติเหล่านั้นในคลาสได้ ดูเหมือนจะซ้ำซ้อนสำหรับฉันเล็กน้อย
user1721803

1
@ user1721803 ตามที่ Dave แนะนำคุณอาจต้องการเก็บคุณสมบัติ / วิธีการบางอย่างไว้โดยไม่เปิดเผย นี่คือเมื่อใช้ส่วนขยาย พิจารณามุมมองคุณสามารถเชื่อมต่อ IBOutlets และ IBActions ทั้งหมดของคุณในส่วนขยายและเปิดเผยวิธีการที่อนุญาตให้เริ่มต้น / อัปเดต Outlets และ Actions สามารถมอบหมายกลับได้
GoodSp33d

@MaxSeelemann คุณช่วยสาธิตวิธีสร้าง "a (สาธารณะ) คุณสมบัติแบบอ่านอย่างเดียวให้เป็นแบบอ่านเขียนภายในได้ไหม? ขอบคุณ.
allenlinli

คำตอบนี้ระบุนามสกุลในไฟล์ "Class + CategoryName.swift" ถูกต้องหรือไม่ ??
Ritesh.mlk

47
  1. ประเภท

=> ใน Objective C เมื่อคุณต้องการเพิ่มฟังก์ชันการทำงานเพิ่มเติมให้กับคลาสที่ไม่มีการสืบทอดคุณเพียงแค่ใช้หมวดหมู่สำหรับมัน

=> มาพร้อมกับไฟล์. hและ. mของตัวเอง

=> Categoryใช้เพื่อเพิ่มวิธีการใหม่ไม่ใช่คุณสมบัติ

  1. ส่วนขยายคลาส
-> In Objective C, when you want to make behaviour of some property private you use class extension.

-> it comes with **.h** file only.

-> mainly for properties.

หมายเหตุ: เมื่อเราเพิ่มไฟล์ใหม่และเลือกตัวเลือกของวัตถุประสงค์ c ประเภทจะแสดงหมวดหมู่และ "หมวดหมู่ใน" ไม่ใช่ "คลาสย่อยของ" ดังนั้นจึงแสดงเป็น

@interface className (categoryName)
@end

- คุณจะได้รับสองไฟล์. hและ. m พร้อมชื่อไฟล์เป็น ( className + categoryName.hและclassName + categoryName.m )

และในกรณีขยายคุณจะได้รับ

@interface className()
@end

- คุณจะได้รับไฟล์เดียวที่มีชื่อเป็นclassName_extensionName.h

  • ในหมวดหมู่คุณไม่ได้เป็นเจ้าของชั้นเรียน แต่อยู่ในส่วนขยายของคุณ

5
@Prasanna: class extension มาพร้อมกับไฟล์. m เท่านั้นและไม่อยู่ใน. h
Saggy

1
นามสกุลคลาสมาพร้อมกับไฟล์. h เท่านั้นไม่ใช่. m
Nishu_Priya

32
  1. หมวดหมู่เป็นวิธีการเพิ่มวิธีการลงในคลาสไม่ว่าจะมีซอร์สโค้ดหรือไม่ซึ่งหมายความว่าคุณสามารถเพิ่มหมวดหมู่ให้กับคลาสพื้นฐานเช่นNSStringและในคลาสแบบกำหนดเอง

    สามารถเพิ่มส่วนขยายลงในคลาสที่มีซอร์สโค้ดได้เท่านั้นเนื่องจากคอมไพเลอร์รวบรวมซอร์สโค้ดและส่วนขยายในเวลาเดียวกัน

  2. เราสามารถเพิ่มตัวแปรอินสแตนซ์และคุณสมบัติพิเศษในส่วนขยายคลาสได้ แต่ไม่สามารถเพิ่มในหมวดหมู่ได้

  3. ตัวแปรและวิธีการใด ๆ ภายในส่วนขยายจะไม่สามารถเข้าถึงคลาสที่สืบทอดมาได้

  4. หมวดหมู่และส่วนขยายโดยทั่วไปสร้างขึ้นเพื่อจัดการฐานรหัสขนาดใหญ่ แต่หมวดหมู่เป็นวิธีการขยายคลาส API ในไฟล์ต้นฉบับหลายไฟล์ในขณะที่ส่วนขยายเป็นวิธีการเพิ่มวิธีการที่จำเป็นนอกไฟล์อินเทอร์เฟซหลัก

  5. ใช้หมวดหมู่เมื่อคุณต้องแบ่งรหัสคลาสเดียวกันออกเป็นไฟล์ต้นฉบับที่แตกต่างกันตามฟังก์ชันการทำงานที่แตกต่างกันและส่วนขยายเมื่อคุณต้องการเพิ่มวิธีการที่จำเป็นบางอย่างในคลาสที่มีอยู่นอกไฟล์อินเทอร์เฟซหลัก นอกจากนี้เมื่อคุณต้องการแก้ไขตัวแปรอินสแตนซ์ที่ประกาศต่อสาธารณะในคลาสตัวอย่างเช่นอ่านอย่างเดียวเพื่ออ่านเขียนคุณสามารถประกาศอีกครั้งในส่วนขยาย


3
ฉันอ่านคำถามที่คล้ายกัน 5 ข้อพร้อมคำตอบมากมายและนี่คือสิ่งที่ดีที่สุด ขอขอบคุณ!
น้ำผึ้ง

1
คุณสามารถเพิ่มคุณสมบัติในหมวดหมู่ได้เช่นกัน ดูคำตอบของ @Pebby
atulkhatri

7

ส่วนขยาย : เพื่อทำให้วิธีการเป็นส่วนตัวและเพื่อเพิ่มคุณสมบัติของคลาสที่กำหนดเองของเราเองไม่ใช่ของคลาส Apple

หมวดหมู่ : เพื่อเพิ่มวิธีการอื่น ๆ NSStringในชั้นเรียนที่มีอยู่ไม่ได้ทรัพย์สินก็สามารถนำมาใช้สำหรับทั้งชั้นเองและชั้นแอปเปิ้ลเช่น


เรียบง่ายและสง่างาม ติดตามต่อไป
Abdul Yasin

3

เรายังสามารถมีคุณสมบัติโดยใช้ชุดคุณสมบัติที่เกี่ยวข้องในคลาสประเภท

@interface SomeClass (Private)

@property (nonatomic, assign) id newProperty;

@end

NSString * const kNewPropertyKey = @"kNewPropertyKey";

@implementation SomeClass (Private)

@dynamic newProperty;

- (void)setNewProperty:(id)aObject
{
    objc_setAssociatedObject(self, kNewPropertyKey, aObject, OBJC_ASSOCIATION_ASSIGN);
}

- (id)newProperty
{
    return objc_getAssociatedObject(self, kNewPropertyKey);
}

@end

อ้างอิง: http://inchoo.net/dev-talk/ios-development/how-to-add-a-property-via-class-category/


2
@interface SomeClass ()


- (void) anAdditionalMethod;


@end

ผมว่ามันไม่ใช่วิธีประกาศ Category หมวดหมู่ต้องมีชื่อ

@interface SomeClass (XYZ)


- (void) anAdditionalMethod;


@end

ตัวอย่างเช่น

@interface NSMutableArray (NSMutableArrayCreation)

+ (id)arrayWithCapacity:(NSUInteger)numItems;
- (id)initWithCapacity:(NSUInteger)numItems;

@end

ประกาศสำหรับ NSMutableArray โดย Apple


นี่คือวิธีที่คุณประกาศและขยายไม่ใช่หมวด -> @interface SomeClass ()
ChavirA

0

ส่วนขยาย ios คล้ายกับ c #, java abstract class หรือ interface
ios category คล้ายกับ c #, java class extension


4
คำตอบของคุณก็เช่นเดียวกับ "แมวคล้ายกับเสือตอบชายตาบอด" Lol
Muruganandham K

1
มันไม่ได้เป็นความจริง เป็นคำอธิบายที่ตรงและรวดเร็วที่สุดหากคุณรู้จัก c # หรือ java
Add080bbA

ไม่ได้บรรยายมากและแทบไม่ได้ตอบคำถาม
KVISH

0

หมวดหมู่

หมวดหมู่ถูกใช้เมื่อคุณสร้างไฟล์ที่มีเมธอดจำนวนมากดังนั้นจึงให้ความสะดวกแก่คุณในการแบ่งคลาสเดียวออกเป็นโมดูลต่างๆนอกจากนี้หากมีการเปลี่ยนแปลงใด ๆ กับหมวดหมู่คอมไพเลอร์จะไม่เสียเวลาในการคอมไพล์โปรเจ็กต์ทั้งหมด หมวดหมู่ไม่สามารถเพิ่มตัวแปรหรือคุณสมบัติใหม่และค้นหาได้ไม่เกินคลาสพาเรนต์คุณสามารถแทนที่เมธอดในหมวดหมู่ได้ แต่ไม่ใช่ความคิดที่ดีเพราะไม่สามารถแทนที่เมธอดได้อีกนอกจากนี้โฟลว์ยังสามารถมีผลได้เนื่องจากหมวดหมู่ทั้งหมดมี ระดับลำดับชั้นเดียวกันและด้วยเหตุนี้สองประเภทที่อยู่ในคลาสหลักเดียวกันอาจมีอยู่ในขณะรันนอกจากนี้ยังสามารถสร้างวิธีการป้องกันโดยใช้หมวดหมู่

ส่วนขยาย

ส่วนขยายช่วยให้คุณสามารถแทนที่คุณสมบัติหรือเพิ่มคุณสมบัติใหม่ให้กับคลาสพาเรนต์ที่มีอยู่ได้เหมือนกับหมวดหมู่ที่ไม่มีชื่อและแสดงเป็นคลาส @interface () ไม่มีไฟล์. m อยู่และต้องใช้วิธีการที่ประกาศในส่วนขยาย ใน @implementation ของไฟล์พาเรนต์

ความช่วยเหลือเพิ่มเติมที่ลิงค์นี้


0

นี่คือความเข้าใจของฉัน:

ส่วนต่อขยายที่มักจะถูกนำมาใช้เพื่อเพิ่มคุณสมบัติพิเศษเพื่อตัวเองของเรา " ชั้นเอง " เราสามารถเพิ่มเมธอดส่วนตัวหรือคุณสมบัติเพื่อขยายอินเตอร์เฟสคลาสซึ่งสามารถใช้ได้ภายในการนำคลาสไปใช้

ส่วนขยายจะต้องเขียนภายในไฟล์เดียวกับคลาส ดังนั้นคุณจึงไม่สามารถเขียนส่วนขยายสำหรับประเภทที่กำหนดไว้ล่วงหน้าเช่น String, Float เป็นต้น

ในทางกลับกันหมวดหมู่สามารถใช้เพื่อเพิ่มวิธีการพิเศษให้กับคลาสที่มีอยู่ก่อน ตัวอย่างเราสามารถสร้างวิธีการของเราเองโดยการขยายคลาส String โปรดทราบว่าเราไม่สามารถสร้างคุณสมบัติพิเศษในหมวดหมู่ได้ ข้อได้เปรียบหลักของหมวดหมู่คือเราสามารถเขียนหมวดหมู่ในไฟล์อื่น ๆ นอกไฟล์ที่คลาสของคุณออกได้

นอกจากนี้ในขณะที่สร้างหมวดหมู่คุณควรตั้งชื่อให้ในวงเล็บ แต่สำหรับนามสกุลไม่จำเป็นต้องมีชื่อ ดังนั้นบางครั้งจึงเรียกว่าหมวดหมู่ที่ไม่ระบุตัวตน


คุณไม่ได้ติดตาม
อับดุลยาซิน

@iPhoneDeveloper เราสามารถเขียนส่วนขยายสำหรับประเภทที่กำหนดไว้ล่วงหน้า โปรดตรวจสอบลิงค์นี้ - stackoverflow.com/a/33942484/2060508
yo2bh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.