转:http://tigercat1977.blog.163.com/blog/static/214156112201211381456747/
第一讲:Obj-C 基本语法
2012-12-03 08:19:44| 分类: Objective-C | 标签:objective-c |字号大中小 订阅
类的申明
函数 / 消息的定义方法
字段作用域
1. Objective-C是C遇见的面向对象的一个超集。
2. Objective-C最初只是为了给C设计的一款最小化的面向对象的语法。
同时完全兼容C语言。
3. 为了避免和已有的C, C++关键字冲突。所有的Obj-C 关键字都有@开始,
4. 比如: @class, @interface, @implementation, @public, @private,
@protected, @try, @catch, @throw, @finally, @end, @protocol,
@selector, @synchronized, @encode, @defs
基本面向过程
比较项目 OC 和 C 语言的对比
基本类型 char, short, int, long long, BOOL
布尔 TRUE, FALSE YES, NO
基本语句 if else switch for while do goto
for 额外扩展 for ( xx in xx ) OC 特有
面向对象概述
比较项目 OC
基类 NSObject
单继承 是单继承
接口 支持接口(协议)@prtocol 接口方法可选实现
多继承 使用接口来实现多继承
多态 支持多态
抽象类 支持抽象类
异常处理 简单的异常处理 @try @catch @finally
虚函数 所有的函数都是虚函数
类定义
OC 类分为 2 个文件, 一个是 .h 一个是 .m 文件
.h 文件存放类, 函数申明
.m 文件存放类的具体实现
类申明使用关键字 @ interface , @ end 来申明
类实现使用关键字 @implementation , @end 来实现
对象方法 和 类方法
如果申明和实现一个类的函数, 需要使用 + 或者 - 来用在函数开始。
+ 表示类的方法。
- 表示对象的方法。
类声明 <Dog.h>
#import <Foundation/Foundation.h>
@interface Dog : NSObject
{
( 写 字段 实例变量)
}
(括号外写 方法 函数消息)
@end
类的实现<Dog.m>
#import "Dog.h"
@implementation Dog
( 方法 函数消息 的实现 )
@end
To import or include?
Objective - C 使用了 # import 来包含头文件。优点就是同一个头文件只能包含一次。
C/C++ 使用 # include 来包含头文件。缺点就是同一个头文件可能被包含多次
Obj - C 语言包含头文件格式 : # import head.h
C/C++ 语言包含头文件格式 : # ifndef _HEAD_H_
# define _HEAD_H_
# endif
创建 / 销毁 OC 对象
创建对象: Dog *dog = [Dog alloc];
初始化构造函数: [dog init];
销毁对象: [dog release];
类中字段和函数
@ interface Dog: NSObject
{
int age; 字段定义在此
}
函数定义在此
- (void) setAge:(int) newAge;
@ end
字段定义
C++ 和 OC 在变量申明一样,都有 public protected private 三种作用域
(C++) public: protected: private:
(OC) @public @protected @private
OC 缺省是 @ protected
C++ 和 OC 在函数声明不一样
OC 函数全部都是 public 类型(用另外方式实现 private 化)
变量必须定义在 类 { } 之间的地方
字段作用域解释
@ public 对象该字段是全局,均可访问
@ protected 对象该字段是保护类型,只有在类本身或者子类中可以访问
@ private 只能在类内部才可以访问
类申明比较
所有OC类,接口申明必须要带 *
这里 * 即表示指针也表示引用
OC:
Dog * myDog;
这里 * 既表示 真正的指针,也表示引用
可以通过 myDog -> dog 或者 myDog.dog 这些方法来访问
类声明 <Dog.h>
#import <Foundation/Foundation.h> @interface Dog : NSObject { int age; } - (id) init; - (id) initWithAge:(int) newAge; - (id) getAge; - (void) setAge:(int) newAge; @end
类实现 <Dog.m>
# import "Dog.h" @ implementation Dog - (id) init
{ return [self initWithAge:10]; } - (id) initWithAge:(int)newAge
{ self = [super init]; if (self) { age = newAge; } return self; } - (int) getAge
{ return age; } - (void) setAge:(int) newAge
{ age = newAge; } @ end
函数定义
在OC中属性是申明只能在 @interface { 和 } 之间。
属性的使用和 C 语言类似
在 @interface { 和 } 之间不能定义方法。
定义方法是:
- (int) f: (int) x;
这里 - 表示对象方法, + 表示类的方法和 C++ 类似
返回值或者参数的类型申明是使用()包括
参数分割使用 : 来分开
函数定义例子
典型的函数和定义变量定义
多参数情况
- (int) f:(int) x; 类似于 C 中 int f(int x);
函数不带参数(函数名:f)
- (int) f 类似C的 int f() 函数
带一个参数(函数名:f: x)
- (int) f: (int) x 类似C的 int f(int x) 函数
带两个参数(函数名:f::)
- (float) f: (int) x :(int) y 类似C的 float f(int x, inty) 函数
带两个参数(函数名:f::)
- (float) f: (int) x :(int) y 注:OC 中不欢迎这样写
参数能够在: 前面设置一个标签 lable,标签 lable 也是函数名的一部分,
标签是为了方便阅读(不带标签实际上也有一个匿名标签)
比如上述函数可以变成
- (float) f: (int) x g:(int) y 这里 g 表示标签, 函数名是 f:g:
第一个参数不能有标签,事实上函数名就是第一个参数的标签
函数调用对比
C 例子
int insertObjectAtIndexBefore ( Object o, int index, boolean before );
int ret = obj -> insertObjectAtIndexBefore( str, 2, true);
OC 例子
- (int) insertObject:(NSObject *)o AtIndex: (int)index Before:(BOOL)before
int ret = [obj insertObject:10 AtIndex:2 Before:TRUE];
多参数的方法调用
OC 不是严格的函数重载
@ interface Foo : NSObject
{ }
- (int) g:(int) x;
- (int) g:(float) x; // 错误:这个方法和前一个方法冲突(因为没有标签)
- (int) g:(int) x:(int) y; // 正确:两个匿名的标签
- (int) g:(int) x:(float) y; // 错误:也是两个匿名标签
- (int) g:(int) x andY:(int) y; // 正确:第二个标签是 andY
- (int) g:(int) x andY:(float) y; // 错误:第二个标签也是 andY
- (int) g:(int) x andAlsoY:(int) y; // 正确:第二个标签是 andAlsoY
@ end
Message 消息机制
使用发送目标对象一个消息来达到处理函数
使用如下的格式来出来发送消息
[object message]
object.message
因为是动态绑定,消息和接受者都是在运行时动态绑定在一起。
object 表示一个对象或者一个类,
message 消息也可以认为是一个函数。
函数作用域申明
OC 在 .h 头文件定义的多有函数都是 public 类型
OC 通过 Categories 来实现函数的私有化
Question
首先创建 Dog 类
dog.h 申明
#import <Foundation/Foundation.h> @interface Dog : NSObject { // 写 字段(实例变量) @protected // 保护类型 int ID; // 狗的ID @public // 公有类型 int age; // 狗的年纪 @private // 私有类型 float price; // 狗的价格 } // 括号外写 方法 // 凡是以 initXXX 开头的都是构造函数 - (id) init; // 函数名为 init 不带参数 - (id) initWithID:(int)newID; // 函数名为 initWithID: 带一个init 的参数 - (id) initWithID:(int)newID andAge:(int)newAge; // 函数名为 initWithID:andAge: 带两个参数,都为int - (id) initWithID:(int)newID andAge:(int)newAge andPrice:(float)newPrice; // 函数名为 initWithID:andAge:andPrice 带有3个参数 都为init - (void) setID:(int)newID; - (int) getID; // set/get ID - (void) setAge:(int)newAge; - (int) getAge; - (void) setPrice:(float)newPrice; - (int) getPrice; - (void) setID:(int)newID andAge:(int)newAge; // setID:andAge: 2个参数 - (void) setID:(int)newID andAge:(int)newAge andPrice:(float)newPrice; // setID:andAge:andPrice 3个参数 @end
dog.m 实现
#import "Dog.h" @implementation Dog - (id) init { return [self initWithID:1]; /* self = [super init]; // super 表示父类 // self 表示对象自己 if (self) { ID = 1; age = 2; price = 60.0f; } return self; */ } // return 调用下边的函数 - (id) initWithID:(int)newID { return [self initWithID:newID andAge:2]; /* self = [super init]; if (self) { ID = newID; age = 2; price = 60.0f; } return self; */ } // return 调用下边的函数 - (id) initWithID:(int)newID andAge:(int)newAge { return [self initWithID:newID andAge:newAge andPrice:60.1f]; } // 调用下边的函数 - (id) initWithID:(int)newID andAge:(int)newAge andPrice:(float)newPrice { self = [super init]; if (self) { ID = newID; age = newAge; price = newPrice; } return self; } // 最终的构造函数 - (void) setID:(int)newID { ID = newID; } - (int) getID { return ID; } - (void) setAge:(int)newAge { age = newAge; } - (int) getAge { return age; } - (void) setPrice:(float)newPrice { price = newPrice; } - (int) getPrice { return price; } - (void) setID:(int)newID andAge:(int)newAge { ID = newID; age = newAge; } - (void) setID:(int)newID andAge:(int)newAge andPrice:(float)newPrice { ID = newID; age = newAge; price = newPrice; } @end
main.m 为
#import <Foundation/Foundation.h>
#import "Dog.h" int main (int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); Dog *dog1 = [Dog alloc]; [dog1 init]; int ID = [dog1 getID]; int age = [dog1 getAge]; float price = [dog1 getPrice]; NSLog(@"dog1 ID is %d, age is %d, price is %f\n", ID, age ,price); // 输出:dog1 ID is 1, age is 2, price is 60.000000 // Dog *dog2 = [Dog alloc]; // [dog2 initWithID:100 andAge:26 andPrice:68.88]; // 将上边两行嵌套在一起,推荐这样做 Dog *dog2 = [[Dog alloc] initWithID:100 andAge:26 andPrice:68.88f]; ID = [dog2 getID]; age = [dog2 getAge]; price = [dog2 getPrice]; NSLog(@"dog2 ID is %d, age is %d, price is %f\n", ID, age ,price); // 输出: dog2 ID is 100, age is 26, price is 68.000000 [dog2 setID:2012 andAge:38 andPrice:87.2f]; ID = [dog2 getID]; age = [dog2 getAge]; price = [dog2 getPrice]; NSLog(@"dog2 new ID is %d, age is %d, price is %f\n", ID, age ,price); // 输出:dog2 new ID is 2012, age is 38, price is 87.000000 } return 0; }