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

本文介绍了Objective-C中的核心概念,包括@interface用于声明类的特性,如数据成员、属性和方法,而@implementation则是实现这些特性的代码。Objective-C 2.0引入的属性简化了代码,提高了效率。文件结构通常将@interface放在.h文件中,@implementation放在.m文件中。此外,文章还涉及继承和复合的概念,以及对象实例化的过程。

前言

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指令的执行文件。
Objective-C File就是存放@implementation指令的执行文件。
Heather File就是存放@interface指令的头文件。
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则会自动管理内存,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提示了程序处理速度。

, NO 是 0 , BOOL 本身就是个 char 。 4、IBOutlet、IBAction是啥玩意,总能看到。 这两个东西其实在语法中没有太大的作用。如果你希望在Interface Builder中能看 ,NO是0,BOOL本身就是个char。 4、IBOutlet、IBAction是啥玩意,总能看到。 这两个东西其实在语法中没有太大的作用。如果你希望在Interface Builder中能看到这个控件对象,那么在定义的时候前面加上IBOutlet,在IB里就能看到这个对象的outlet,如果你希望在Interface Builder里控制某个对象执行某些动作,就在方法前面加上(IBAction)。 而这两个东西实际上和void是一样的。 5、nil。 Objective-C里的NULL(空)就这么写,表示空指针。 6、为什么是@”字符串”而不是”字符串” 前面加上@符号,编译器在编译的时候会在程序中给你留出位置,这样才能保证这个字符串不会丢失。反正记住,如果你要想把某些字符串写死在程序里,就要用@”字符串”,如果忘了用@,程序应该会出错。 superzhou大侠指正: 6、为什么是@”字符串”而不是”字符串” ”字符串”是C的字符串,@”"是把C的字符串转成NSString的一个简写. 在需要NSString的地方才需要这个转化,例如NSLog里面. 在需要C string的地方,还是用”字符串”的. 另外,@”"这个转换是不支持中文的.例如NSLog(@”字符串”); 是一定输出不了中文的. 四、Objective-C 2.0 Objective-C 2.0是Leopard新增加的一门语言,其实和原来的Objective-C是一样的。主要是增加了属性。详细的内容这里不写了,可以参阅Allen Dang的这篇文章,写的很明白。 http://blog.codingmylife.com/?p=81 五、总结 现在来总结一下怎么看Objective-C的代码和怎么开始学Objective-C吧。 1、记住Objective-C就是C,不是火星语,这个很关键。 2、记住你自己看不懂不表示脑子迟钝,大部分人第一次看Objective-C的代码可能比你还要迟钝。 3、把CocoaChina.com加入收藏夹,看不明白代码就来再看一遍这篇开宗明义的好文。 4、文档很关键,当你看不懂某些东西说的是什么的时候,先查Cocoachina,再看英文文档里面的API说明,尤其这个类是以NS开头的时候。再不行就去google搜,直接把你要查的方法贴进google,通常能找到不少人也在问同样的问题,自然也有热心人活雷锋帮助回答。 5、可以看hello world例子,但是不能总看,看多了真的会晕。另外,千万要放弃苹果官方的Currency Converter货币转换的例子,那个例子是毒药,刚学的时候越看越蒙。 6、学习一门语言最好的方法是先用,和学外语一样,当你会说的时候自然会读。给自己设立一个简单的目标,比如做一个简单的程序,然后一点点解决问题。这样学习起来比只看例子快得多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值