入门学习Objective-C中的@interface与@implementation

    xiaoxiao2021-03-25  112

    前言

    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则会自动管理内存,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提示了程序处理速度。

    转载请注明原文地址: https://ju.6miu.com/read-5200.html

    最新回复(0)