Frage

In Ruby gibt es Module und Sie können eine Klasse von „Misch-in“ Modul erweitern.

module MyModule
  def printone
    print "one" 
  end
end

class MyClass
  include MyModule
end

theOne = MyClass.new
theOne.printone 
>> one

In Objective-C, finde ich, dass ich eine Reihe von gemeinsamen Methoden habe, dass ich eine Reihe von Klasse zu „erben“ will. Was andere Weise kann ich dieses Ziel zu erreichen, ohne eine gemeinsame Klasse zu schaffen und alle von dieser gemeinsamen Klasse ableiten?

War es hilfreich?

Lösung

Bearbeiten :. Änderungen hinzugefügt, weil einige Leute fühlen Ich bin verantwortlich für die Grenzen von Objective-C

Kurze Antwort : Sie können es nicht. Objective-C nicht über das Äquivalent von Ruby Mixins.

Etwas weniger kurze Antwort : Objective-C hat etwas mit dem wohl gleichen Geschmack: Protokolle. Protokolle (Schnittstellen in einigen anderen Sprachen), sind eine Möglichkeit, eine Reihe von Methoden, um eine Klasse zu definieren, dass Nimmt die Protokolle zur Umsetzung begehen. Ein Protokoll unterstützt keine Implementierung though. Diese Beschränkung verhindert Protokolle als exakte Äquivalent Ruby Mixins verwendet wird.

Noch weniger kurze Antwort: Doch die Objective-C-Laufzeit hat eine exponierte API, die Sie mit dem dynamischen spielen können Funktionen der Sprache. Dann treten Sie außerhalb der Sprache, aber Sie können mit Standardimplementierungen haben Protokolle (auch als konkrete Protokolle). Vladimir Antwort zeigt eine Möglichkeit, das zu tun. An diesem Punkt scheint es mir bekommen Sie Ruby-Mixins in Ordnung.

Allerdings bin ich nicht sicher, würde ich empfehlen, das zu tun. In den meisten Fällen passen andere Muster, die Rechnung ohne Spiele mit der Laufzeit zu spielen. Zum Beispiel können Sie ein Teilobjekt haben, dass die Mixed-in-Methode implementieren ( hat-a statt ist-a ). Das Spiel mit der Laufzeit ist in Ordnung, hat aber zwei Nachteile:

  • Sie machen Ihren Code weniger lesbar, wie es Leser erfordert viel mehr als die Sprache zu kennen. Sicher kann man (und sollte) kommentieren, aber denken Sie daran, dass alle notwendigen Kommentar als Implementierungs Defekt gesehen werden kann.

  • Sie sind abhängig von , die Implementierung der Sprache. Sicher, Apple-Plattformen sind mit Abstand die häufigsten sind für Objective-C, aber nicht vergessen Cocotron oder GNUstep (oder Etoilé), die unterschiedliche Laufzeiten haben, die oder nicht mit Apple auf dieser Hinsicht kompatibel sind.

Als Randbemerkung, ich Zustand unterhalb diesen Kategorien kann nicht Zustand (Instanzvariablen) zu einer Klasse hinzuzufügen. Durch die Verwendung der Laufzeit-API, können Sie diese Einschränkung heben. Dies geht über den Rahmen dieser Antwort jedoch.

Lange Antwort:

Zwei Objective-C bietet aussehen wie mögliche Kandidaten: Kategorien und Protokolle. Kategorien sind nicht wirklich die richtige Wahl hier, wenn ich die Frage richtig zu verstehen. Die richtige Funktion ist ein Protokoll.

Lassen Sie mich ein Beispiel geben. Angenommen, Sie ein paar Klassen wollen eine bestimmte Fähigkeit genannt haben „singen“. Dann definieren Sie ein Protokoll:

@protocol Singer
    - (void) sing;
@end

Jetzt können Sie erklären, dass jede Ihrer eigenen Klassen das Protokoll die folgende Art und Weise nimmt:

@interface Rectangle : Shape <Singer> {
    <snip>
@end

@interface Car : Vehicle <Singer> {
    <snip>
@end

Mit dem er erklärt, dass sie das Protokoll verabschieden sie sich verpflichten, die sing Methode zu implementieren. Zum Beispiel:

@implementation Rectangle

- (void) sing {
    [self flashInBrightColors];
}

@end

@implementation Car

- (void) sing {
    [self honk];
}

@end

Dann nutzen Sie diese Klassen zum Beispiel wie folgt aus:

void choral(NSArray *choir) // the choir holds any kind of singer
{
    id<Singer> aSinger;
    for (aSinger in choir) {
        [aSinger sing];
    }
}

Beachten Sie, dass die Sänger in der Gruppe keine gemeinsame Oberklasse haben müssen. Beachten Sie auch, dass eine Klasse kann nur eine übergeordnete Klasse haben, aber viele angenommen Protokolle. Hinweis schließlich, dass die Typprüfung durch den Compiler durchgeführt wird.

In der Tat ist das Protokoll Mechanismus Mehrfachvererbung für das mixin Muster verwendet. Die Mehrfachvererbung ist stark eingeschränkt, weil ein Protokoll keine neue Instanzvariablen zu einer Klasse hinzufügen kann. Ein Protokoll beschreibt nur eine öffentliche Schnittstelle Adopters implementieren müssen. Im Gegensatz zu Ruby-Module ist es nicht eine Implementierung enthalten.

Das ist das Beste daraus. Lassen Sie uns Erwähnung Kategorien jedoch.

Eine Kategorie ist nicht deklariert in spitzen Klammern, aber in Klammern. Der Unterschied besteht darin, dass eine Kategorie definiert werden kann für eine bestehende Klasse um es zu erweitern, ohne sie Subklassen. Sie können sogar so für eine Systemklasse tun. Wie Sie sich vorstellen können, ist es möglich, Kategorien zu verwenden, etwas ähnliches zu mixin zu implementieren. Und sie wurden auf diese Weise für eine lange Zeit in der Regel als Kategorie NSObject (die typische Wurzel verwendetder Vererbungshierarchie), in einem solchen Ausmaß, dass sie „informell“ Protokolle genannt wurden.

Es ist informell, weil 1- keine Typüberprüfung durch den Compiler durchgeführt wird, und 2- das Protokoll Methoden der Umsetzung ist optional.

Es gibt keine Notwendigkeit, heute Verwendungskategorien wie Protokolle, vor allem, weil die formalen Protokolle jetzt erklären können, dass einige ihrer Methoden sind optional mit dem Schlüsselwort @optional oder erforderlich ist (Standardeinstellung) mit @required.

Kategorien sind immer noch nützlich einige domänenspezifischen Verhalten zu einer vorhandenen Klasse hinzuzufügen. NSString ist ein gemeinsames Ziel für die.

Es ist auch interessant, darauf zu hinweisen, dass die meisten (wenn nicht alle) NSObject Einrichtungen sind in der Tat in einem NSObject Protokoll erklärt. Dies bedeutet, dass es nicht wirklich überzeugend ist NSObject als gemeinsame Oberklasse für alle Klassen zu verwenden, obwohl dies immer noch häufig aus historischen Gründen erfolgt, und gut ... weil es kein Nachteil ist, so zu tun. Aber einige Systemklassen, wie NSProxy, sind nicht NSObject.

Andere Tipps

Shameless Stecker: ObjectiveMixin

Es nutzt die Vorteile von Objective-C-Laufzeit der Fähigkeit von Methoden zu einer Klasse im laufenden Betrieb hinzugefügt (im Gegensatz zu Kategorien gegenüber, die nur Compile-Zeit sind). Check it out, es funktioniert ziemlich gut und in ähnlicher Weise wie Rubys Mixins.

Sie können buchstäblich den Code mixin #include verwenden. Dies ist nicht ratsam und ist gegen alle Religionen in Objective-C, jedoch funktioniert perfekt.

Bitte, tun Sie es nicht in der Produktion Code.

zum Beispiel in der Datei:

MixinModule.header (sollte nicht auf das Ziel kompiliert oder kopiert werden)

-(void)hello;

MixinModule.body (sollte nicht auf das Ziel kompiliert oder kopiert werden)

-(void)hello{
    NSLog(@"Hello");
}

in mixin Klasse:

@interface MixinTest : NSObject
#include "MixinModule.header"
@end

@implementation MixinTest
#include "MixinModule.body"
@end

Anwendungsfall:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]){
    @autoreleasepool {
        [[[MixinTest new] autorelease] hello];
    }
    return 0;
}

Bitte, tun Sie es nicht in der Produktion Code.

Dies ist meine nehmen Mixins bei der Umsetzung in Objective-C, ohne die Objective-C-Laufzeit direkt zu verwenden. Vielleicht hilfreich es ist jemand: https://stackoverflow.com/a/19661059/171933

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top