object-c语法
Objective-C:C的超集
Objective-Objective-C是C语言的严格超集--任何C语言程序不经修改就可以直接通过Objective-C编译器,在Objective-C中使用C语言代码也是完全合法的。Objective-C被描述为盖在C语言上的薄薄一层,因为Objective-C的原意就是在C语言主体上加入面向对象的特性。
第一个 Objective-C 程序,基于Xcode 4.3.1:
#import <Foundation/Foundation.h> int main(int argc, char *argv[]) { @autoreleasepool {
NSLog(@"Hello World!");
} return ;
}
消息传递
C++里,送一个消息给对象(或者说调用一个方法)的语法如下:
obj.method(argument);
Objective-C则写成:
[obj method: argument];
此二者并不仅仅是语法上的差异,还有基本行为上的不同。
这里以一个汽车类(car class)的简单例子来解释Objective-C的消息传递特性:
[car fly];
典型的C++意义解读是"调用car类别的fly方法"。若car类别里头没有定义fly方法,那编译肯定不会通过。但是Objective-C里,我们应当解读为"发提交一个fly的消息给car对象",fly是消息,而car是消息的接收者。car收到消息后会决定如何回应这个消息,若car类别内定义有fly方法就运行方法内之代码,若car内不存在fly方法,则程序依旧可以通过编译,运行期则抛出异常。
此二种风格各有优劣。C++强制要求所有的方法都必须有对应的动作,且编译期绑定使得函数调用非常快速。缺点是仅能借由virtual关键字提供有限的动态绑定能力。Objective-C天生即具备鸭子类型之动态绑定能力,因为运行期才处理消息,允许发送未知消息给对象。可以送消息给整个对象集合而不需要一一检查每个对象的类型,也具备消息转送机制。同时空对象nil接受消息后默认为不做事,所以送消息给nil也不用担心程序崩溃。
字符串
Objective-C提供了一个助记符可以方便地从常量值创建NSString对象。要使用这个助记符,你需要做的全部事情,是在普通的双引号字符串前放置一个@符号,如下面的例子所示:
NSString* myString = @"My String\n";
NSString* anotherString = [NSString stringWithFormat:@"%d %s", , @"String"]; // 从一个C语言字符串创建Objective-C字符串
NSString* fromCString = [NSString stringWithCString:"A C string"
encoding:NSASCIIStringEncoding];
类
Objective-C 的类规格说明包含了两个部分:定义(interface)与实现(implementation)。定义(interface)部分包含了类声明和实例变量的定义,以及类相关的方法。实现(implementation)部分包含了类方法的实际代码。
下图展现了声明一个叫做 MyClass 的类的语法,这个类继承自 NSObject 基础类。类声明总是由 @interface 编译选项开始,由 @end 编译选项结束。类名之后的(用冒号分隔的)是父类的名字。类的实例(或者成员)变量声明在被大括号包含的代码块中。实例变量块后面就是类声明的方法的列表。每个实例变量和方法声明都以分号结尾。
类的定义文件遵循C语言之惯例以.h为后缀,实现文件以.m为后缀。
类声明图
Interface
定义部分,清楚定义了类的名称、数据成员和方法。 以关键字@interface作为开始,@end作为结束。
@interface MyObject : NSObject {
int memberVar1; // 实体变量
id memberVar2; //访问权限默认为protected
} +(return_type) class_method; // 类方法(静态方法) -(return_type) instance_method1; // 实例方法
-(return_type) instance_method2: (int) p1;
-(return_type) instance_method3: (int) p1 andPar: (int) p2;
@end
加号(+)代表类方法(class method),不需要实例就可以调用,与C++ 的静态函数(static member function)相似.
减号(-)即是一般的实例方法(instance method)。
这里提供了一份意义相近的C++语法对照,如下:
class MyObject : public NSObject {
protected:
int memberVar1; // 实体变量
void * memberVar2; public:
static return_type class_method(); // 类方法(静态方法) return_type instance_method1(); // 实例方法
return_type instance_method2( int p1 );
return_type instance_method3( int p1, int p2 );
}
Objective-C定义一个新的方法时,冒号(:)代表参数传递
- (void) setColorToRed: (float)red Green: (float)green Blue:(float)blue; /* 方法声明*/ [myColor setColorToRed: 1.0 Green: 0.8 Blue: 0.2]; /* 调用方法*/
这个方法的签名是setColorToRed:Green:Blue:。每个冒号后面都带着一个float类别的参数,分别代表红,绿,蓝三色。
Implementation
实现区块则包含:公开方法的实现,以及定义私有(private)变量及方法。 以关键字@implementation作为区块起头,@end结尾。
@implementation MyObject {
int memberVar3; //访问权限默认为private
} +(return_type) class_method {
.... //method implementation
}
-(return_type) instance_method1 {
....
}
-(return_type) instance_method2: (int) p1 {
....
}
-(return_type) instance_method3: (int) p1 andPar: (int) p2 {
....
}
@end
Interface区块内的变量默认权限为protected,声明于implementation区块的变量则默认为private
创建对象
Objective-C创建对象需通过alloc以及init两个消息。alloc的作用是分配内存,init则是初始化对象。 init与alloc都是定义在NSObject里的方法
MyObject * my = [[MyObject alloc] init];
在Objective-C 2.0里,若创建对象不需要参数,则可直接使用new
MyObject * my = [MyObject new];
方法
方法声明:
调用方法:
消息被中括号( [ ] )包括。中括号中间,接收消息的对象在左边,消息(包括消息需要的任何参数)在右边。例如,给myArray变量传递消息insertObject:atIndex:消息,你需要使用如下的语法:
[myArray insertObject:anObj atIndex:];
为了避免声明过多的本地变量保存临时结果,Objective-C允许你使用嵌套消息。每个嵌套消息的返回值可以作为其他消息的参数或者目标。例如,你可以用任何获取这种值的消息来代替前面例子里面的任何变量。所以,如果你有另外一个对象叫做myAppObject拥有方法,可以访问数组对象,以及插入对象到一个数组,你可以把前面的例子写成如下的样子:
[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex:];
虽然前面的例子都是传递消息给某个类的实例,但是你也可以传递消息给类本身。当给类发消息,你指定的方法必须被定义为类方法,而不是实例方法。你可以认为类方法跟C++类里面的静态成员有点像(但是不是完全相同的)。
下面的例子演示了一个类方法如何作为类的工厂方法。在这里,arrayWithCapacity是NSMutableArray类的类方法,为类的新实例分配内容并初始化,然后返回给你。
NSMutableArray* myArray = nil; // nil 基本上等同于 NULL // 创建一个新的数组,并把它赋值给 myArray 变量
myArray = [NSMutableArray arrayWithCapacity:];
属性
属性是用来代替声明存取方法的便捷方式。属性不会在你的类声明中创建一个新的实例变量。他们仅仅是定义方法访问已有的实例变量的速记方式而已。暴露实例变量的类,可以使用属性记号代替getter和setter语法。类还可以使用属性暴露一些“虚拟”的实例变量,他们是部分数据动态计算的结果,而不是确实保存在实例变量内的。
实际上可以说,属性节约了你必须要写的大量多余的代码。因为大多数存取方法都是用类似的方式实现的,属性避免了为类暴露的每个实例变量提供不同的getter和setter的需求。取而代之的是,你用属性声明指定你希望的行为,然后在编译期间合成基于声明的实际的getter和setter方法。
属性声明应该放在类接口的方法声明那里。基本的定义使用@property编译选项,紧跟着类型信息和属性的名字。你还可以用定制选项对属性进行配置,这决定了存取方法的行为。下面的例子展示了一些简单的属性声明:
@interface Person : NSObject {
@public
NSString *name;
@private
int age;
} @property(copy) NSString *name;
@property(readonly) int age; -(id)initWithAge:(int)age;
@end
属性的访问方法由@synthesize关键字来实现,它由属性的声明自动的产生一对访问方法。另外,也可以选择使用@dynamic关键字表明访问方法会由程序员手工提供。
@implementation Person
@synthesize name;
@dynamic age; -(id)initWithAge:(int)initAge
{
age = initAge; // 注意:直接赋给成员变量,而非属性
return self;
} -(int)age
{
return ; // 注意:并非返回真正的年龄
}
@end
属性可以利用传统的消息表达式、点表达式或"valueForKey:"/"setValue:forKey:"方法对来访问。
Person *aPerson = [[Person alloc] initWithAge: ];
aPerson.name = @"Steve"; // 注意:点表达式,等于[aPerson setName: @"Steve"];
NSLog(@"Access by message (%@), dot notation(%@), property name(%@) and direct instance variable access (%@)",
[aPerson name], aPerson.name, [aPerson valueForKey:@"name"], aPerson->name);
为了利用点表达式来访问实例的属性,需要使用"self"关键字:
-(void) introduceMyselfWithProperties:(BOOL)useGetter
{
NSLog(@"Hi, my name is %@.", (useGetter ? self.name : name)); // NOTE: getter vs. ivar access
}
类或协议的属性可以被动态的读取。
int i;
int propertyCount = ;
objc_property_t *propertyList = class_copyPropertyList([aPerson class], &propertyCount); for ( i=; i < propertyCount; i++ ) {
objc_property_t *thisProperty = propertyList + i;
const char* propertyName = property_getName(*thisProperty);
NSLog(@"Person has a property: '%s'", propertyName);
}
快速枚举
比起利用NSEnumerator对象或在集合中依次枚举,Objective-C 2.0提供了快速枚举的语法。在Objective-C 2.0中,以下循环的功能是相等的,但性能特性不同。
// 使用NSEnumerator
NSEnumerator *enumerator = [thePeople objectEnumerator];
Person *p; while ( (p = [enumerator nextObject]) != nil ) {
NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// 使用依次枚举
for ( int i = ; i < [thePeople count]; i++ ) {
Person *p = [thePeople objectAtIndex:i];
NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// 使用快速枚举
for (Person *p in thePeople) {
NSLog(@"%@ is %i years old.", [p name], [p age]);
}
快速枚举可以比标准枚举产生更有效的代码,由于枚举所调用的方法被使用NSFastEnumeration协议提供的指针算术运算所代替了。
object-c语法的更多相关文章
- Object C语法学习
#synthesize关键字: 根据@property设置,自动生成成员变量相应的存取方法,从而可以使用点操作符来方便的存取该成员变量 . @implementation 关键字,表明类的实现 @en ...
- Vue 双向数据绑定原理分析 以及 Object.defineproperty语法
第三方精简版实现 https://github.com/luobotang/simply-vue Object.defineProperty 学习,打开控制台分别输入以下内容调试结果 userInfo ...
- Object Pascal 语法之异常处理
http://www.cnblogs.com/spider518/archive/2010/12/30/1921298.html 3 结构化异常处理 结构化异常处理(SHE)是一种处理错误的手段,使得 ...
- 【转】话说我打算一天学完object c语法,系列1--------来自书Objective-c程序设计
原文网址:http://blog.csdn.net/zengraoli/article/details/8993466 类型: NSString NSInteger NSLong控制台输出 NSObj ...
- Object C语法学习笔记(一)
1.@property与@synthesize配对使用. @property预编译指令的作用是自动声明属性的setter和getter方法. @synthesize 创建了该属性的访问代码 功能:让编 ...
- 【IOS 开发】Object - C 语法 之 流程控制
1. if 条件语句 if 表达式 : 表达式是一个 整型 或者 布尔型, 0 或者 FALSE 为 FALSE, 大于 0 为 TRUE; 代码示例 : /********************* ...
- 【IOS 开发】Object - C 语法 之 类型转换
作者 : 万境绝尘 (octopus_truth@163.com) 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/3913507 ...
- Object C语法学习笔记(二)
1.@property与@synthesize配对使用. @property预编译指令的作用是自动声明属性的setter和getter方法. @synthesize 创建了该属性的访问代码 功能:让编 ...
- Delphi_04_Delphi_Object_Pascal_基本语法_02
这里简单的描述Object的语法中的基本内容,数据类型.因为代码是自描述的所以不废话,直接贴代码. { 用户自定义类型 1.数组 2.动态数组 3.记录 4.集合 } program UserDefi ...
- Object.defineproperty实现数据和视图的联动
Object.defineproperty语法 var o = {}; // 创建一个新对象 // Example of an object property added with definePro ...
随机推荐
- chrome 小技巧:保持元素的hover状态
审查元素,选中需要hover的标签 点击"Styles"菜单中的":hov",弹出 Force element state 选中相应的 :hover :acti ...
- linux同一台机子上用多个git 账号
Step 1 - Create a New SSH KeyWe need to generate a unique SSH key for our second GitHub account. ssh ...
- DBLinq (MySQL exactly) Linq To MySql
http://blog.csdn.net/feihu_guest/article/details/7346948 DBLinq (MySQL exactly) Linq To MySql http:/ ...
- winform 子窗体刷新父窗体的数据
建一个接口 比如 iMainForm接口内声明个方法 比如 Refresh()主窗体 实现这个接口 主窗体打开子窗体时这样写 子窗体.Owner = this;子窗体.ShowDialog(); -- ...
- hadoop入门篇-hadoop下载安装教程(附图文步骤)
在前几篇的文章中分别就虚拟系统安装.LINUX系统安装以及hadoop运行服务器的设置等内容写了详细的操作教程,本篇分享的是hadoop的下载安装步骤. 在此之前有必要做一个简单的说明:分享的所有内容 ...
- [转]使用Nginx实现反向代理
使用Nginx实现反向代理 解释 正向代理的概念 正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器这个代理服务器呢,他能访问 ...
- CentOS启动网络提示connect: Network is unreachable(配置静态路由)
ls /etc/sysconfig/network-script/ifcfg-eth0 一.看是否在上述目录下存在ifcfg-eth0 这个文件,若存在则按下面的步骤操作: 1.手工配置ip看能不能配 ...
- windows下使用vscode编写运行以及调试Python
更新于2018年10月: 首先去python官网下载python3 地址:https://www.python.org/downloads/windows/ 下载好后直接安装 记得勾选添加环境变量 ...
- MySQL优化技巧之四:mysql数据库开发常见问题及优化[转]
mysql 数据库是被广泛应用的关系型数据库,其体积小.支持多处理器.开源并免费的特性使其在 Internet 中小型网站中的使用率尤其高.在使用 mysql 的过程中不规范的 SQL 编写.非最优的 ...
- [转]NSIS:使用SectionSetFlags根据不同环境自动勾选特定区段
转自: http://www.flighty.cn/html/bushu/20140526_232.html 在微软SQL2000+SP4集成安装版安装包中可以根据目标操作系统自动勾选对应的版本, ...