Objective-C หลายมรดก


88

ฉันมี 2 คลาสหนึ่งมี methodA และอีกคลาสรวม methodB ดังนั้นในคลาสใหม่ฉันต้องแทนที่ method methodA และ methodB ดังนั้นฉันจะบรรลุการสืบทอดหลายรายการในวัตถุประสงค์ C ได้อย่างไร ฉันสับสนเล็กน้อยกับไวยากรณ์

คำตอบ:


136

Objective-C ไม่รองรับการสืบทอดหลายรายการและคุณไม่จำเป็นต้องใช้ ใช้องค์ประกอบ:

@interface ClassA : NSObject {
}

-(void)methodA;

@end

@interface ClassB : NSObject {
}

-(void)methodB;

@end

@interface MyClass : NSObject {
  ClassA *a;
  ClassB *b;
}

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;

-(void)methodA;
-(void)methodB;

@end

ตอนนี้คุณต้องเรียกใช้วิธีการบน ivar ที่เกี่ยวข้อง เป็นรหัสมากกว่า แต่ไม่มีการสืบทอดหลายรายการเป็นคุณลักษณะภาษาในวัตถุประสงค์ -C


8
การจัดองค์ประกอบมักจะเป็นแนวทางที่ดีกว่าการสืบทอดโดยเฉพาะอย่างยิ่งหากคุณทำการทดสอบหน่วยจำนวนมากกับโค้ด ช่วยเพิ่มความยืดหยุ่นมากขึ้นโดยที่คุณสามารถสลับการใช้งานได้อย่างง่ายดายโดยไม่ต้องกำหนดคลาสใหม่ มีประโยชน์อย่างยิ่งเมื่อคุณต้องการพูดสลับ ClassA และ ClassB สำหรับวัตถุจำลอง แม้ในขณะที่รันไทม์สลับการใช้งาน (เช่น FTPFileStore กับ LocalFileStore) ก็จะสะอาดขึ้นด้วยองค์ประกอบ นั่นไม่ได้หมายความว่าการสืบทอดจะไม่มีที่มา แต่ความจำเป็นในการสืบทอดหลาย ๆ ครั้งจะแนะนำให้ฉันคิดใหม่ในการออกแบบของฉัน;)
d11wtq

1
ฉันไม่เข้าใจเรื่องนี้ คุณไม่จำเป็นต้องสร้างอินสแตนซ์ClassAและClassB? ไม่เรียกร้องmethodA:เกี่ยวกับการMyClassอย่างใดเรียกโดยอัตโนมัติmethodA:ในวันที่ClassA?
zakdances

1
ไม่ได้ แต่คุณยังสามารถแชร์พฤติกรรมผ่านการส่งข้อความได้ซึ่งในตอนแรก OOP ควรจะใช้งานได้ หากคุณไม่คิดว่าคุณต้องการการสืบทอดในทันทีและพิจารณาวิธีแก้ปัญหาโดยใช้องค์ประกอบแทนคุณจะพบว่าคุณเริ่มจัดโครงสร้างโปรแกรมของคุณด้วยวิธีที่ดูแลรักษาได้ง่ายขึ้น แน่นอนว่า ObjC มีมรดกพื้นฐานสำหรับกรณีที่ใช้มันได้อย่างถูกต้อง
d11wtq


1
d11wtq ตอบโจทย์มาก! นอกจากนี้การส่งต่อข้อความช่วยให้คุณข้ามขั้นตอนของการนำ methodA และ methodB ไปใช้ใหม่ได้ ข้อความสามารถส่งต่อไปยังวัตถุที่เหมาะสมได้โดยอัตโนมัติด้วยการทำงานเพียงเล็กน้อย developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
arsenius

3

นี่คือวิธีที่ฉันตั้งรหัส singletonPattern เป็น "ผู้ปกครอง" โดยทั่วไปฉันใช้โปรโตคอลและหมวดหมู่ร่วมกัน

สิ่งเดียวที่ฉันไม่สามารถเพิ่มได้คือ "ivar" ใหม่อย่างไรก็ตามฉันสามารถผลักดันมันด้วยวัตถุที่เกี่ยวข้องได้

#import <Foundation/Foundation.h>
@protocol BGSuperSingleton
+(id) singleton1;
+(instancetype)singleton;
@end

@interface NSObject (singleton) <BGSuperSingleton>

@end

static NSMutableDictionary * allTheSingletons;

+(instancetype)singleton
{
    return [self singleton1];
}
+(id) singleton1
{
    NSString* className = NSStringFromClass([self class]);

    if (!allTheSingletons)
    {
        allTheSingletons = NSMutableDictionary.dictionary;
    }

    id result = allTheSingletons[className];

    //PO(result);
    if (result==nil)
    {
        result = [[[self class] alloc]init];
        allTheSingletons[className]=result;
        [result additionalInitialization];
    }
    return result;
}

-(void) additionalInitialization
{

}

เมื่อใดก็ตามที่ฉันต้องการให้คลาส "สืบทอด" BGSuperSingleton นี้ฉันก็ทำ:

#import "NSObject+singleton.h"

และเพิ่ม @interface MyNewClass () <BGSuperSingleton>


2
หมวดหมู่ไม่ใช่การสืบทอดหลายรายการ เป็นวิธีหนึ่งในการยึดเมธอด / ฟังก์ชันไปยังคลาสที่มีอยู่แล้ว การสืบทอดหลายรายการอนุญาตให้คลาสที่สามเป็นการรวมกันของคลาสเดียวหรือมากกว่า (รวมถึงตัวแปร) ฉันชอบหมวดหมู่ หมวดหมู่มีประโยชน์มาก แต่ไม่ใช่มรดกหลายอย่าง
Lloyd Sargent

แต่คลาสย่อยของ UIViewController สามารถ "รองรับ" ได้เช่นกันในกรณีนี้ฉันควรต้องการรูปแบบซิงเกิลตัน
Septiadi Agus

ในทางเทคนิค NSManagedObject ทั้งหมด "สามารถเรียก" [obj singleton] ได้แล้ว ฉันตั้งค่าสิ่งที่ฉันต้องการด้วยการสนับสนุนของโปรโตคอล ดีพอ ๆ กับการสืบทอดหลาย ๆ อย่างอยู่แล้ว นี่เป็นเพียงกรณีที่ฉันต้องการให้คลาสย่อยสนับสนุนทั้งอินเทอร์เฟซและการใช้งานของพาเรนต์ หากเฉพาะการนำไปใช้งานองค์ประกอบที่ชัดเจนก็คือหนทางที่จะไป
Septiadi Agus

เพียงแค่เพิ่มโปรโตคอลเช่น <BGSuperSingleton> ไม่ได้ทำให้คลาสนั้นสามารถเรียกเมธอด "singleton" ได้ คุณยังต้องใช้มัน ...
CommaToast

-4

คุณรู้หรือไม่เกี่ยวกับ Protocols โปรโตคอลเป็นวิธีการใช้งานการสืบทอดหลาย ๆ


12
+1 "เพื่อรวบรวมความคล้ายคลึงกันระหว่างชั้นเรียนที่ไม่เกี่ยวข้องกันตามลำดับชั้น" developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
pokstad

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

คุณสามารถรวมโปรโตคอลกับหมวดหมู่หรือองค์ประกอบ
Septiadi Agus

-1 เนื่องจากไม่มีโปรโตคอลสำหรับการสืบทอดหลายรายการเลย ในทำนองเดียวกันในJAVA, Interfacesไม่ได้ที่จะให้หรือมรดกหลายเลียนแบบ
thesummersign

1
@FreeAsInBeer จากเอกสาร ของ Apple โปรโตคอลประกาศอินเทอร์เฟซแบบเป็นโปรแกรมที่คลาสใด ๆ สามารถเลือกใช้ โปรโตคอลช่วยให้สองคลาสมีความสัมพันธ์กันอย่างห่างเหินโดยการถ่ายทอดทางพันธุกรรมเพื่อสื่อสารกันเพื่อบรรลุเป้าหมายบางอย่าง พวกเขาจึงนำเสนอทางเลือกในการ subclassing อย่างที่คุณเห็นApple กำลัง ใช้คลาสย่อยอย่างชัดเจนเช่นการสืบทอด บางที Nikesh รวมสิ่งนี้ไว้ในคำตอบของเขาเองอาจเป็นประโยชน์ในการชี้แจงข้อโต้แย้งของเขา
น้ำผึ้ง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.