/*
object-c的語法學習
main.mm
made by davidsu33

-(BOOL)isKindOfClass:            classObj
                     是否是其子孫或一員

-(BOOL)isMemberOfClass:            classObj
         是否是其一員

-(BOOL)respondsToSelector:            selector
         是否有這種方法

+(BOOL)instancesRespondToSelector:            selector
         類的物件是否有這種方法

-(id)performSelector:            selector
         執行物件的方法
*/

#import <Foundation/Foundation.h>

typedef struct
{
    float x,y,w,h;
}Rect;

typedef struct
{
    float x,y;
}Point;

@protocol DSShape

@optional
- (int) getArea;

@optional
- (Rect) getBoundingRect;

@optional
- (NSMutableArray*) getPointArray;

@end

@interface DSRectangle : NSObject<DSShape>
{
    Rect _rect;
    NSString* _name;
}

@property (readwrite, nonatomic)
Rect rect;

@property(readwrite, nonatomic)
NSString *name;

- (id) init;
- (void) dealloc;
- (NSString*) className;
- (BOOL) isSqure;
- (void) showInfo;
- (Rect) getBoundingRect;
@end

@implementation DSRectangle
@synthesize rect = _rect, name = _name;

- (id) init
{
    if(self = [super init])
    {
        self.rect = Rect{0,0,0,0};
        self.name = nil;
        NSLog(@"%@ initialize", [self className]);
    }

    return self;
}

- (void) dealloc
{
    NSLog(@"%@ dealloc", [self className]);
}

- (NSString*) className
{
    return NSStringFromClass([self class]);
}

- (BOOL) isSqure
{
    return self.rect.w == self.rect.h;
}

- (void) showInfo
{
    id s = [[NSString alloc] initWithFormat:@"x=%f,y=%f,w=%f,h=%f, name=%@",_rect.x,
                                        _rect.y,_rect.w,_rect.h,self.name];
    NSLog(@"DSRectangle: %@",s);
}

- (Rect) getBoundingRect
{
    return self.rect;
}
@end

@interface DSSqure : DSRectangle
- (id) init;
- (void) dealloc;
- (float) sideLength;
@end

@implementation DSSqure
- (id) init
{
    if(self = [super init])
    {
        NSLog(@"%@ initialize", [self className]);
    }

    return self;
}

- (void) dealloc
{
    NSLog(@"%@ dealloc",[self className]);
}

- (float) sideLength
{
    return self.rect.w;
}
@end

#define SyntaxTest(x)\
    do{\
        NSLog(@"%@ = %@", [[NSString alloc] initWithCString:#x], [email protected]"TRUE":@"FALSE");\
    }while(0)

void dynamic_attr_test()
{
    DSRectangle *re = [[DSRectangle alloc] init];
    re.name = @"Rectangle";
    re.rect = Rect{10,20,200,300};

    DSSqure *sq = [[DSSqure alloc] init];
    sq.name = NSStringFromClass([sq class]);
    sq.rect = Rect{30,40,500,600};

    //NSLog(@"rectangle name:%@", re.name);
    [re showInfo];
    [sq showInfo];

    NSLog(@"\n-------------------isKindOfClass-----------------");
    SyntaxTest([re isKindOfClass: [NSObject class]]);
    SyntaxTest([re isKindOfClass: [DSRectangle class]]);
    SyntaxTest([DSRectangle isKindOfClass: [NSObject class]]);
    SyntaxTest([DSRectangle isKindOfClass: [DSRectangle class]]);

    //動態語法測試
    //isKindOfClass 物件是否是該類,或者該類祖先的例項
    SyntaxTest([re isKindOfClass: [NSObject class]]);
    SyntaxTest([re isKindOfClass: [DSRectangle class]]);

    //isMemberOf 物件是否是某一個類的例項
    NSLog(@"\n-------------------isMemberOfClass-----------------");
    SyntaxTest([re isMemberOfClass: [NSObject class]]);
    SyntaxTest([re isMemberOfClass: [DSRectangle class]]);

    SyntaxTest([DSRectangle isMemberOfClass: [NSObject class]]);
    SyntaxTest([DSRectangle isMemberOfClass: [DSRectangle class]]);

    //如果例項是輸入引數,則selector是類的成員函式返回TRUE
    //如果類名稱是輸入引數,則selector是類的靜態函式返回TRUE,否則返回FALSE
    NSLog(@"\n-------------------respondsToSelector-----------------");
    SyntaxTest([re respondsToSelector: @selector(init)]);
    SyntaxTest([re respondsToSelector: @selector(NoThat)]);
    SyntaxTest([re respondsToSelector: @selector(showInfo)]);

    SyntaxTest([DSRectangle respondsToSelector: @selector(init)]);
    SyntaxTest([DSRectangle respondsToSelector: @selector(NoThat)]);
    SyntaxTest([DSRectangle respondsToSelector: @selector(showInfo)]);

    //檢視協議介面
    SyntaxTest([re respondsToSelector: @selector(getArea)]);
    SyntaxTest([re respondsToSelector: @selector(getBoundingRect)]);

    SyntaxTest([DSRectangle respondsToSelector: @selector(getArea)]);
    SyntaxTest([DSRectangle respondsToSelector: @selector(getBoundingRect)]);

    //判斷該方法是例項介面(類成員函式)還是類函式(靜態函式)
    NSLog(@"\n-------------------instancesRespondToSelector-----------------");
    /*SyntaxTest([re instancesRespondToSelector: @selector(init)]);
    SyntaxTest([re instancesRespondToSelector: @selector(NoThat)]);
    SyntaxTest([re instancesRespondToSelector: @selector(showInfo)]);
    */

    //instancesRespondToSelector只能輸入類,不能寫其他的
    SyntaxTest([DSRectangle instancesRespondToSelector: @selector(init)]);
    SyntaxTest([DSRectangle instancesRespondToSelector: @selector(NoThat)]);
    SyntaxTest([DSRectangle instancesRespondToSelector: @selector(showInfo)]);

    /*
    1. respondsToSelector既可以檢查類(是否響應指定類方法),也可以檢查例項(是否響應指定例項方法)
    2. instancesRespondToSelector只能寫在類名後面,但檢測的是例項(是否響應指定例項方法)
    可以認為[Test instancesRespondToSelector:sel]等價於[obj respondsToSelector:sel]
    */

    //[re release];
    //[sq release];
}

int main()
{
    id arp = [[NSAutoreleasePool alloc] init];
    dynamic_attr_test();
    getchar();
    [arp drain];

    return 0;
}