2010-03-06 3 views
20

Kann eine Objective-c-Schnittstelle mehr als eine Implementierung haben? Beispiel I könnte eine Schnittstelle haben, aber 2 Implementierungen, wobei ich ein Array oder ein anderes verwende, wo ich einen Stack..etc verwende, um es zu implementieren.Kann eine Objective-c-Schnittstelle mehr als eine Implementierung haben?

Wenn ja, wie nennt man es/Syntax?

+0

Wie wäre es mit "Protokolle"? Es ist näher an Java/C# Schnittstellen. Was ist das, was ich will? – user48545

Antwort

25

Objective-C das Konzept eines Protokolls hat, die die Spezifikation einer Schnittstelle ist. Über Protokolle unterstützt Objective-C die mehrfache Vererbung der Spezifikation (aber nicht die Implementierung). Also, ein bisschen verwirrend, die @ Interface-Syntax definiert eigentlich die Klasse (Implementierung), die nur einzelne Vererbung unterstützt, kann aber die Implementierung von vielen/mehreren Vererbung von Protokolle oder Spezifikationen von Schnittstellen angeben. Am Ende ist dies Java sehr ähnlich.

Zum Beispiel:

@protocol SomeInterface 
- (void)interfaceMethod1; 
- (void)interfaceMethod2; 
@end 

@interface SomeClass:NSObject <SomeInterface> 
@end 

@interface AnotherClass:NSObject <SomeInterface> 
@end 

Instanzen von beiden SomeClass oder AnotherClass sowohl behaupten, dass sie die Implementierung, die für die SomeInterfaceProtokoll bereitzustellen.

Objective-C ist dynamisch typisiert und erfordert nicht, dass das Objekt tatsächlich die Nachricht angibt, die an es gesendet wird. Mit anderen Worten, können Sie wahllos jede Methode aufrufen Sie auf SomeClass möchten, ob es angegeben ist in seiner Schnittstelle oder eines seiner Protokolle oder nicht (nicht, dass dies notwendigerweise eine produktive oder positiv sein würde zu tun).

Daher würde alle der folgenden kompilieren (wenn auch mit Warnungen) und gut laufen, obwohl die Nachrichten/Methoden ohne Implementierung im Grunde eine no op in diesem Fall ist. Objective-C hat einen ziemlich komplizierten (und sehr coolen) Prozess zum Aufrufen/Weiterleiten von Methoden, der etwas über den Rahmen dieser Frage hinausgeht.

SomeClass * someObject = [[SomeClass alloc] init; 
[someObject someUnspecifiedMethod]; // Compiles with warning - no op 
[someObject interfaceMethod1]; 

Wenn Sie etwas zu definieren, die jede Klasse sein kann (@interface) geben, sondern implementiert eine spezielle Schnittstelle (@protocol), können Sie so etwas wie folgt verwenden:

id <SomeInterface> obj; 

obj könnte entweder ein SomeClass oder AnotherClass Objekt halten.

+0

Sie haben Recht ... Ich beantwortete eine viel mehr "Basis" -Frage (und nicht wirklich die, die der OP verlangte) ... nach dem erneuten Lesen kann ich sehen, dass der OP wahrscheinlich nach etwas mehr Ausschau gehalten hat Ihre Antwort/abstrakte Fabriken/Klassencluster. – rcw3

3

Sie meinen zum Beispiel wie folgt aus:

@interface MasterViewController : 
    UIViewController <GKPeerPickerControllerDelegate, 
        GKSessionDelegate, 
        UITextFieldDelegate, 
        UITableViewDelegate, 
        AVAudioRecorderDelegate> { 
} 
+0

Oder meinst du eigentlich mehr als einen @ implementation/@ end block? –

+0

Diese Suche ergab die Möglichkeit, mehrere Delegaten zu deklarieren, ohne separate Klassen und Implementierungen zu erstellen. Das hat perfekt funktioniert. Danke 2 Jahre später. –

24

Vielleicht sollten Sie Cocoa-Muster namens Class Cluster versuchen. Um es zu verwenden, müssen Sie die öffentliche Klasse SomeClass und zwei private Unterklassen SomeArrayClass und SomeStackClass erstellen. Wenn Sie den Stack verwenden müssen, erstellt Ihr öffentlicher Klassenkonstruktor die Instanz und gibt sie als öffentlich verfügbare Instanz SomeClass zurück.

+1

Dies ist genau das Muster, das Sie verwenden möchten. – bbum

+0

Wie wäre es mit "Protokolle"? Es ist näher an Java/C# Schnittstellen. Das ist was ich will. – user48545

20

(Wenn Sie eine Stimme abgeben, geben Sie Roman eine Stimme - seine Antwort war zuerst, ist richtig, nur ein Beispiel fehlte).

Sie sprechen über eine Class Cluster. Schauen Sie sich zum Beispiel die NSString Klasse an.

Es gibt NSString:

@interface NSString : NSObject 

Und NSMutableString:

@interface NSMutableString : NSString 

Beide, die erklären, eine extrem kleine Menge von Methoden in der Erklärung des Kerns Klasse. Wenn Sie NSString von einer Unterklasse ableiten würden, um Ihre eigene String-Klasse zu implementieren, müssten Sie nur diese Kernmethoden implementieren. Alle anderen in NSString implementierten Methoden sind in Bezug auf diese Kernmethoden implementiert. Und ebenso werden die Mutationsmethoden unter Verwendung der primitiven Methoden implementiert, die im Kern von NSMutableString deklariert sind.

Jetzt, offensichtlich, die Implementierung aller Veränderlichkeit über - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString (die eine Kernmethode) würde grob ineffizient sein. Zur Laufzeit merkt man also, dass niemals eine Instanz von NSString oder NSMutableString ist, sondern nur Instanzen von Unterklassen (die eigentlich keine Unterklassen sind), aber sie könnten genauso gut im Kontext sein dieser Diskussion).

Und diese Unterklassen - die zur Laufzeit verwendete Implementierungsklasse - überschreiben fast alle Methoden von NSString und NSMutableString, um hoch optimierte Implementierungen der spezifischen Operationen bereitzustellen.

Also, würden Sie so etwas wie:

@interface MyAbstractClass : NSObject 
... declare factory methods here ... 
... declare core methods here ... 
@end 

@interface MyAbstractClass(AdditionalFunctionality) 
... declare convenience here ... 
@end 

Dann bei der Umsetzung, Implementierung alle Kern Methoden wie @throw @"Must use subclass" und alle AdditionalFunctionality Methoden in Bezug auf die Kernmethoden.

Dies könnte ganz privat sein - nicht in einem Header überhaupt, auch:

@interface MyStackClass: MyAbstractClass @end

@implementation MyStackClass ... die Kern Methoden implementieren und überschreiben die Zusätzliche Funktionalitätsmethoden, die Optimierung benötigen ... @end

Wiederholen Sie für Ihre zusätzlichen Arten von Klassen. Implementieren Sie dann Factory-Methoden für MyAbstractClass, die bei Bedarf Instanzen der Unterklassen zurückgeben.

Verwandte Themen