前言
Objective-C是一门面向对象语言,是对于C语言的扩展。面向对象编程又是学习Objective-C的重中之重,但是刚入门学习时,容易被Objective-C的语法规范搞糊涂。本文尝试用倒叙的手段,由深入浅的学习Objective-C,可能更容易被读者接受,尤其是针对有着一定编程经验的读者。
@interface部分
接口(@interface)是类为对象提供特性描述。在@interface 中我们可以声明对象的数据成员、属性、以及方法。
示例:
@interface AllWeatherRadial
{
float rainHandling;
float snowHandling;
}
- (void) setRainHanding: (float) rainHanding;
- (float) rainHandling;
- (void) setSnowHanding: (float) snowHanding;
- (float) snowHandling;
@end
以上代码就是通过@interface指令为对象AllWeatherRadial声明函数以及数据成员。
@implementation部分
在@implementation中,我们用来写使得接口能够正常工作的代码。用我的话说用作实现@interface定义的方法,真正使程序能够运行在@implementation里。
注意:在@implementation中,我们不必按顺序实现接口中定义的方法,也可以在其中定义@interface本没有的方法以及数据成员。但是一旦在@implementation中声明了某个方法,那么这个方法就是当前对象的私有方法,无法被子类继承。
示例:
@implementation AllWeatherRadial
- (void) setRainHanding:(float) rh
{
rainHandling = rh;
}
- (float) rainHandling
{
return (rainHandling);
}
- (void) setSnowHanding:(float) sh
{
snowHandling = sh;
}
- (float) snowHandling
{
return (snowHandling);
}
@end
我想经验丰富的读者早已看出,通过@implementation实现了对rainHandling和snowHandling两个数据成员进行get和set,读写操作的实现。
属性
刚才的代码想必太过繁琐,Objective-C 2.0中引入了属性。属性的出现使得Objective-C代码更加简洁,带来的好处是bug更少,工作效率更高。
让我们来看示例代码:
@interface AllWeatherRadial
{
float rainHandling;
float snowHandling;
}
//- (void) setRainHanding: (float) rainHanding;
//- (float) rainHandling;
//- (void) setSnowHanding: (float) snowHanding;
//- (float) snowHandling;
@property float rainHandling;
@property float snowHandling;
@end
“//”是注释符号,@property命令代替了原来需要两行代码实现的声明内容。
@implementation AllWeatherRadial
@synthesize rainHandling;
@synthesize snowHandling;
//- (void) setRainHanding:(float) rh
//{
// rainHandling = rh;
//}
//- (float) rainHandling
//{
// return (rainHandling);
//}
//- (void) setSnowHanding:(float) sh
//{
// snowHandling = sh;
//}
//- (float) snowHandling
//{
// return (snowHandling);
//}
@end
“//”是注释符号,@synthesize命令代替了原来冗长的实现代码。@property和@synthesize大大方便了使用者,在编译时Objective-C的机制依然会生成原先的get/set方法。
文件结构
刚才说了Objective-C类的源代码分为两部分,一部分是接口(@interface),另一部分是@implementation实现了接口所有的方法。我们将@interface放在已.h为后缀的头部文件中,同时将@implementation放在以.m为后缀的执行文件中。
以下是基本的文件构造范例:
可以清楚的看到Car,Tire,Engine,Slant6,AllWeatherRadial分别对应了一个.h以及一个.m,这里要注意main.m因为是主函数,主要是一些实现代码,因此也是以.m结尾。
另外通过Command+N快捷键命令,同样看到两种不同的Objective-C文件。
Objective-C File就是存放@implementation指令的执行文件。
Heather File就是存放@interface指令的头文件。
回到刚才的对象AllWeatherRadial,它现在被拆成AllWeatherRadial.h和AllWeatherRadial.m两个文件,其中AllWeatherRadial.m文件头部就要加上一句代码。
import "AllWeatherRadial.h"
继承与复合
继承是面向对象重要的特性,他避免了许多重复的代码。Objective-C不同于C++,它是单继承只能继承一个父类。
刚才的AllWeatherRadial他继承了Tire类,完整的代码如下:
#import <Cocoa/Cocoa.h>
#import "Tire.h"
@interface AllWeatherRadial : Tire
{
float rainHandling;
float snowHandling;
}
@property float rainHandling;
@property float snowHandling;
@end
Tire类通过#import引入Tire.h头文件,通过中缀符表示AllWeatherRadial继承自Tire。
复合好比是音乐中的作曲,将多个组件组合在一起使用。这里有一个Car类他同时用到了Tire和Engine两个个类,那么我们应该怎么实现呢?
Car.h文件如下:
#import <Cocoa/Cocoa.h>
@class Engine;
@class Tire;
@interface Car : NSObject
{
NSString *name;
Engine *engine;
NSMutableArray *tires;
}
@property (copy) NSString *name;
@property (retain) Engine *engine;
//- (void)setName: (NSString *)newName;
//-(NSString *) name;
- (Engine *) engine;
- (void) setEngine: (Engine *) newEngine;
- (Tire *) tireAtIndex: (int) index;
- (void) setTire: (Tire *) tire atIndex: (int) index;
- (void) print;
@end
Car.m文件如下:
#import "Car.h"
#import "Engine.h"
#import "Tire.h"
@implementation Car
@synthesize name;
@synthesize engine;
- (id) init
{
if (self = [super init])
{
self.name = @"Car";
tires = [[NSMutableArray alloc] init];
for (int i = 0; i < 4; i++) {
[tires addObject: [NSNull null]];
}
}
return (self);
}
- (void) print
{
NSLog(@"%@ has:", self.name);
for (int i = 0; i < 4; i++) {
NSLog(@"%@", [self tireAtIndex: i]);
}
NSLog(@"%@", engine);
}
- (void) setTire:(Tire *)tire atIndex:(int)index
{
[tires replaceObjectAtIndex: index withObject: tire];
}
- (Tire *) tireAtIndex:(int)index
{
return [tires objectAtIndex:index];
}
@end
代码中出现了NSMutableArray类,这是一个可变数组,不限制数组的长度,并且能够在数组中随意添加或删除对象,并且完成了为对象tires的定义。
添加对象操作,在该数组中添加了4个NSNull对象:
- (id) init
{
if (self = [super init])
{
self.name = @"Car";
tires = [[NSMutableArray alloc] init];
for (int i = 0; i < 4; i++) {
[tires addObject: [NSNull null]];
}
}
return (self);
}
NSMutableArray类里面有一个简便的方法replaceObjectAtIndex: withObject:,在指定的索引位置处必须存在一个能够被替换的对象。setTire:方法使用replaceObjectAtIndex: withObject:从数组集合中删除现有对象并用新对象替代。
- (void) setTire:(Tire *)tire atIndex:(int)index
{
[tires replaceObjectAtIndex: index withObject: tire];
}
- (Tire *) tireAtIndex:(int)index
{
return [tires objectAtIndex:index];
}
对象实例化
既然我们定义了类,并完成了类的实现方法,那么该如何使用它呢?这里推荐一种便捷初始化函数。
对Car类初始化代码如下:
Car *car = [[Car alloc] init];
这里嵌套调用了alloc和init两个方法,同init可以一直初始化到Car的父类,也就是NSObject类(Objective-C类中一切类的基类),而alloc则会自动管理内存,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提示了程序处理速度。
本文介绍了Objective-C中的核心概念,包括@interface用于声明类的特性,如数据成员、属性和方法,而@implementation则是实现这些特性的代码。Objective-C 2.0引入的属性简化了代码,提高了效率。文件结构通常将@interface放在.h文件中,@implementation放在.m文件中。此外,文章还涉及继承和复合的概念,以及对象实例化的过程。
370

被折叠的 条评论
为什么被折叠?



