Objective-C поддържа ли черти/миксини?

Има ли някакви техники за емулиране на характеристики или миксини в Objective-C?

В Scala, например, мога да направя нещо подобно:

trait ControllerWithData {
  def loadData = ...
  def reloadData = ...
  def elementAtIndex = ...
}

trait ControllerWithStandardToolbar {
  def buildToolbar = ...
  def showToolbar = ...
  def hideToolbar = ...
}

class MyTableController extends ControllerWithData 
                        with ControllerWithStandardToolbar {
  def loadView = {
     super.loadView

     loadData
     buildBar
  }
}

По същество това е начин за комбиниране (или смесване) на множество части от функционалност в един клас. Така че в момента имам нещо като универсален UIViewController, от който всички мои контролери подкласират, но би било по-спретнато, ако мога да разбия това и да накарам конкретни контролери да наследят специфично поведение.


person Bill    schedule 08.04.2011    source източник
comment
Искате ли да обясните какво представляват характеристиките и миксините? Концепциите може да се поддържат, но са известни под друго име.   -  person Sherm Pendley    schedule 09.04.2011
comment
Изглежда, че някой е внедрил характеристиките на Obj-C тук: etoileos.com// новини/архив/2011/07/12/1427   -  person Bill    schedule 12.07.2011


Отговори (3)


Няма директна езикова поддръжка, но бихте могли да постигнете нещо подобно с препращане на съобщения. Да приемем, че имате класове черти "Foo" и "Bar", които дефинират съответно методи "-doFoo" и "-doBar". Можете да определите вашия клас да има характеристики, като това:

@interface MyClassWithTraits : NSObject {
    NSMutableArray *traits;
}
@property (retain) NSMutableArray* traits;

-(void) addTrait:(NSObject*)traitObject;
@end

@implementation MyClassWithTraits
@synthesize traits;

-(id)init {
    if (self = [super init]) {
        self.traits = [NSMutableArray array];
    }
    return self;
}

-(void) addTrait:(NSObject*)traitObject {
    [self.traits addObject:traitObject];
}

/*  Here's the meat - we can use message forwarding to re-send any messages
    that are unknown to MyClassWithTraits, if one of its trait objects does
    respond to it.
*/
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector {
    // If this is a selector we handle ourself, let super handle this
    if ([self respondsToSelector:aSelector])
        return [super methodSignatureForSelector:aSelector];

    // Look for a trait that handles it
    else
        for (NSObject *trait in self.traits)
            if ([trait respondsToSelector:aSelector])
                return [trait methodSignatureForSelector:aSelector];

    // Nothing was found
    return nil;
}

-(void) forwardInvocation:(NSInvocation*)anInvocation {
    for (NSObject *trait in self.traits) {
        if ([trait respondsToSelector:[anInvocation selector]]) {
            [anInvocation invokeWithTarget:trait];
            return;
        }
    }

    // Nothing was found, so throw an exception
    [self doesNotRecognizeSelector:[anInvocation selector]];
}
@end

Сега можете да създадете екземпляри на MyClassWithTraits и да добавите каквито искате обекти на „характеристика“:

MyClassWithTraits *widget = [[MyClassWithTraits alloc] init];
[widget addTrait:[[[Foo alloc] init] autorelease]];
[widget addTrait:[[[Bar alloc] init] autorelease]];

Можете да направите тези извиквания към -addTrait: в метода -init на MyClassWithTraits, ако искате всеки екземпляр на този клас да има един и същ вид характеристики. Или можете да го направите както аз направих тук, което ви позволява да присвоите различен набор от черти на всеки екземпляр.

И тогава можете да извикате -doFoo и -doBar, сякаш са имплементирани от уиджет, въпреки че съобщенията се препращат към един от неговите обекти на характеристики:

[widget doFoo];
[widget doBar];

(Редактиране: Добавена обработка на грешки.)

person Sherm Pendley    schedule 08.04.2011
comment
Страхотно! когато видяхте въпроса, не знаехте какви са характеристиките и потърсихте и дори внедрихте това!!! Исках да знам едно нещо, защо е необходимо methodSignatureForSelector да бъде заменен. не е ли достатъчно forwardInvocation? кога се извиква methodSignatureForSelector? какъв е потокът? - person Amogh Talpallikar; 21.08.2013

Характеристиките или миксините не се поддържат от Objective-C, имате само вградена опция за категории. Но за щастие Objective-C Runtime разполага с почти всички инструменти за внедряване на собствена идея при смесване или характеристики с добавяне на методи и свойства към вашия клас по време на изпълнение. Можете да прочетете повече за възможностите, които Objective-C Runtime предоставя за вас, на уебсайта с документация на Apple Objective-C Runtime Документи

Идеята е:

1) Можете да създадете Objective-C протокол (Mixin), в който ще декларирате свойства и методи.

2) След това създавате клас (реализация на Mixin), който ще имплементира методи от този протокол.

3) Създавате свой клас, в който искате да предоставите възможност за композиция с миксини, за да съответства на този протокол (Mixin).

4) Когато вашето приложение се стартира, вие добавяте с времето за изпълнение на Objective-C всички реализации от клас (реализация на Mixin) и свойства, декларирани в (Mixin) във вашия клас.

5) Ето :)

Или можете да използвате някои готови проекти с отворен код като "Alchemiq"

person Aleksey Getman    schedule 30.01.2017

Вероятно търсите категории. Вижте http://macdevelopertips.com/objective-c/objective-c-categories.html.

person Zr40    schedule 08.04.2011
comment
За съжаление не мисля така. Обмислих това и мисля, че ако има някакъв начин да го направя, той ще включва категории. Но категориите ви позволяват да смесвате методи в конкретен клас, а не в множество класове (нали?), така че не мисля, че са достатъчни. Но може и да греша. - person Bill; 09.04.2011
comment
Категориите наистина са дефинирани в един клас. Въпреки това, други класове, наследени от този клас, също наследяват категориите. - person Zr40; 09.04.2011
comment
Категориите определено не са характеристики в смисъла на Scala. Те са по-скоро като частични класове в C# земя. - person Marc W; 09.04.2011