简单类型就不说了,基本上每个语言都差不多。本次我们仅讨论非简单数据类型。
类的继承
头文件
#import <Foundation/Foundation.h> // MyDummy类从NSObject继承而来 @interface MyDummy : NSObject /* * '-'标识是实例方法而不是静态方法; * 返回值用'()'括号括起来,后面跟上方法名; * 冒号后跟上第一个参数类型(继续使用括号括起来)和参数 * 空格后跟第二个参数+冒号+类型+参数名 * 最后用分号结束 */ - (void)foo:(NSString *)username password:(NSString *)passwd; @end
#import "MyDummy.h" @implementation MyDummy /* * 根据声明生成 */ -(void)foo:(NSString *)username password:(NSString *)passwd { NSLog(@"Your name is %@, your password is %@", username, passwd); } @end
#import <Foundation/Foundation.h> #import "MyDummy.h" int main(int argc, const char * argv[]) { @autoreleasepool { NSString *username = [[NSString alloc] initWithFormat:@"Sam"]; NSString *password = [[NSString alloc] initWithFormat:@"sssssssssss"]; MyDummy *dummy = [[MyDummy alloc] init]; [dummy foo:username password:password]; } return 0; }
Category
category和继承有部分类似,不过相对来说比继承关系要简单,我们看一下:
头文件
#import "MyDummy.h" // 注意声明方式与继承不同 @interface MyDummy (MyDummy_SayHello) // 方法的声明方式完全相同 -(void) sayHello:(NSString *)username password:(NSString *)password; @end
实现文件
#import "MyDummy+MyDummy_SayHello.h" @implementation MyDummy (MyDummy_SayHello) -(void) sayHello:(NSString *)username password:(NSString *)password { // 直接调用现有Dummy方法 return [self foo:username password:password]; } @end
#import <Foundation/Foundation.h> #import "MyDummy.h" #import "MyDummy+MyDummy_SayHello.h" int main(int argc, const char * argv[]) { @autoreleasepool { NSString *username = [[NSString alloc] initWithFormat:@"Sam"]; NSString *password = [[NSString alloc] initWithFormat:@"sssssssssss"]; // 声明一个Dummy类的对象 MyDummy *dummy = [[MyDummy alloc] init]; // 对象的方法被扩展了 [dummy sayHello:username password:password]; } return 0; }
Protocol--协议
Protocol在java中对应的是接口。我们在ObjectC中这样使用:
定义protocol
#import <Foundation/Foundation.h> @protocol IComparable <NSObject> -(int) compare:(NSObject *)other; @end
#import <Foundation/Foundation.h> #import "IComparable.h" @interface MyNumber : NSObject <IComparable> @property int num; -(int) compare:(NSObject *)other; @end
实现类的实现文件
#import "MyNumber.h" #import "IComparable.h" @implementation MyNumber @synthesize num; -(int) compare:(NSObject *)other { MyNumber *number = (MyNumber *) other; return [self num] - [number num]; } @end
#import <Foundation/Foundation.h> #import "MyDummy.h" #import "MyDummy+MyDummy_SayHello.h" #import "MyNumber.h" int main(int argc, const char * argv[]) { @autoreleasepool { MyNumber *num1 = [[MyNumber alloc] init]; MyNumber *num2 = [[MyNumber alloc] init]; [num1 setNum:10]; [num2 setNum:100]; NSLog(@"the number is %d", [num1 compare: num2]); } return 0; }
id(动态类型)
ID类型很常见,例如alloc方法,init方法。ID类型很像以前Object Pascal中的variable类型,可以代表任意一种类型;或者你可以将他看成Java中的Object类型。但是一个很明显的差别在于:Java是强类型语言,所以所有的类型转换、方法调用都会检查类型;但ObjectC中,只要你将一个变量定义为id,那么编译器不会再做类型检查工作,甚至连warning都不抛出。
我们看看代码:
父类
#import <Foundation/Foundation.h> @interface ParentClass : NSObject @end
#import "ParentClass.h" @implementation ParentClass @end
#import "ParentClass.h" @interface Child1 : ParentClass -(void) foo1; @end
#import "Child1.h" @implementation Child1 -(void) foo1 { NSLog(@"foo1 invoked."); } @end
#import "ParentClass.h" @interface Child2 : ParentClass -(void) foo2; @end
#import "Child2.h" @implementation Child2 -(void) foo2{ NSLog(@"foo2 invoked."); } @end
#import <Foundation/Foundation.h> #import "ParentClass.h" #import "Child1.h" #import "Child2.h" int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"child1"); Child1 *child1 = [[Child1 alloc] init]; [child1 foo1]; // 下面这一句无法编译 // [child1 foo2]; NSLog(@"child2"); id child2 = [[Child2 alloc] init]; // 下面这一句会爆出异常 // [child2 foo1]; [child2 foo2]; NSLog(@"child3"); id child3 = [[Child2 alloc] init]; // 下面这一段先判断类型,之后调用,安全 if ([child3 isKindOfClass:[Child1 class]]) { // 下面这句不会调用 [child3 foo1]; } // 下面这一段先判断是否包含指定方法,之后调用,同样安全 if ([child3 respondsToSelector:@selector(foo2)]) { // 下面这句会调用 [child3 foo2]; } } return 0; }