Objective-C学习笔记七:类的定义一

[url=http://sarin.iteye.com/blog/1759280]接上文[/url]
我们还是结合之前分数的示例来说明,只是更为详尽。使用XCode创建新的项目Fraction,然后创建Fraction类,此时XCode为我们生成两个文件:Fraction.h和Fraction.m。我们在Fraction.h这个头文件中定义分数类Fraction,在Fraction.m中编写分数类的实现代码,在main.m中编写测试程序。那么在XCode中我们得到如下的项目结构:

[img]http://dl.iteye.com/upload/attachment/0078/8351/c0883bd3-cddd-31d1-b72d-94a5c44d2e86.png[/img]

来看下头文件中的类定义:

//
// Fraction.h
// Fraction
//
// Created by Nan Lei on 13-1-1.
// Copyright (c) 2013年 Nan Lei. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Fraction : NSObject

-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
-(double) convertToNum;

@end

这里的头文件也可以叫做接口文件,它会告知编译器Fraction类的特征,就是包含六个实例方法(用"-"定义的方法)。Fraction类的实现会编写在Fraction.m文件中,代码如下:

//
// Fraction.m
// Fraction
//
// Created by Nan Lei on 13-1-1.
// Copyright (c) 2013年 Nan Lei. All rights reserved.
//

#import "Fraction.h"

@implementation Fraction
{
int numerator;
int denominator;
}

-(void) print
{
NSLog(@"%i/%i",numerator,denominator);
}

-(void) setNumerator:(int)n
{
numerator=n;
}

-(void) setDenominator:(int)d
{
denominator=d;
}

-(int) numerator
{
return numerator;
}

-(int) denominator
{
return denominator;
}

-(double) convertToNum
{
if(denominator!=0){
return (double)numerator/denominator;
}else{
return NAN;
}
}

@end

这和我们之前示例中的是一样的,这里注意一点import语句,我们使用双引号("")来导入头文件,而不是尖括号(<>),原因是Fraction.h是我们自定义的头文件,而不是系统提供的。这样编译器就知道该从什么地方来找到指定的头文件,当然,如果有必要,可以使用更为详细的路径(当我们在不同包下定义了相同的类名的类时)来查找不同位置。
最后来看main.m文件,这是我们之前没有做的一个文件,此时我们拆分main函数到main.m文件中,代码如下:

//
// main.m
// Fraction
//
// Created by Nan Lei on 13-1-1.
// Copyright (c) 2013年 Nan Lei. All rights reserved.
//

#import "Fraction.h"

int main(int argc, const char * argv[])
{
@autoreleasepool {
Fraction *fractionA = [Fraction new];
Fraction *fractionB = [Fraction new];

[fractionA setNumerator:1];
[fractionA setDenominator:3];

NSLog(@"The value of fractionA is %g",[fractionA convertToNum]);

NSLog(@"fractionB is %i / %i",fractionB.numerator,fractionB.denominator);
NSLog(@"The value of fractionB is %g",[fractionB convertToNum]);
}
return 0;
}

要注意这里的import语句,我们仍然引入的是头文件,而不是实现文件。也就是我们只需获取类定义部分的信息就可以了,系统处理时会为我们寻找实现的方法。
这样的代码结构对于之前看到的简单示例来说就复杂多了,这是我们扩大程序规模的必经之路,也更为实用。
我们在上述代码中的Fraction实现文件中编写了两个属性numerator和denominator,并且提供了设置值和取值的方法(类似Java的getter和setter方法),其实更好的写法是在接口文件中使用@property指令来定义属性,还可以省略掉设置值和取值的方法(系统会自动为我们实现),那么Fraction.h的代码修改如下:
#import <Foundation/Foundation.h>


@interface Fraction : NSObject

@property int numerator,denominator;

-(void) print;
-(double) convertToNum;

@end

这样一来,代码就简单很多,那么在实现文件Fraction.m中使用@synthesize指令即可完成对属性numerator和denominator的设置值和取值操作:

#import "Fraction.h"

@implementation Fraction

@synthesize numerator,denominator;

-(void) print
{
NSLog(@"%i/%i",numerator,denominator);
}

-(double) convertToNum
{
if(denominator!=0){
return (double)numerator/denominator;
}else{
return NAN;
}
}

@end

在XCode中运行代码,我们就得到如下的结果:

[img]http://dl.iteye.com/upload/attachment/0078/8353/0536a866-11d8-31ea-9bfe-1cd89b4fd2f6.png[/img]

说明我们的代码是正确的。
我们使用了@property指令,就不用在实现部分定义相应的实例变量,使用@synthesize指令就会告诉编译器为我们生成设置值和取值的方法。方法命名规范是设置值方法setX(x是我们的变量名),注意大小写(和Java Bean的访问器方法类似),取值方法名就是变量名x。当然我们也可以使用点运算符来访问属性,比如我们代码中的写法。同时使用点运算符来为属性赋值也是可以的,只是在代码中没有体现出来。
比如[b]instance.property=value[/b]等价于[b][instance setProperty: value][/b],比如[b]instance.property[/b]等价于[b][instance property][/b]的写法。
之前的代码中我们的方法参数都为一个,下面来看看带有多个参数的方法该如何定义和使用。我们继续来改写分数类Fraction,提供一个可以同时设置分子和分母的方法,很容易想到如下语句[b][fractionA setNumerator:1 setDenominator:3][/b],这是我们很容易想到的方式,但是该方式不具备一个易于理解的方法名,其实我们可以这样来定义这个方法:
 -(void) setTo: (int) n over: (int) d;

下面修改头文件的定义,代码如下:
#import <Foundation/Foundation.h>

@interface Fraction : NSObject

@property int numerator,denominator;

-(void) print;
-(double) convertToNum;
-(void) setTo:(int) n over: (int) d;

@end

这里我们加入了这个方法的定义,那么实现该方法,代码如下:

#import "Fraction.h"

@implementation Fraction

@synthesize numerator,denominator;

-(void) print
{
NSLog(@"%i/%i",numerator,denominator);
}

-(double) convertToNum
{
if(denominator!=0){
return (double)numerator/denominator;
}else{
return NAN;
}
}

-(void) setTo:(int)n over:(int)d
{
numerator=n;
denominator=d;
}

@end

最后修改主函数来进行测试:

#import "Fraction.h"

int main(int argc, const char * argv[])
{
@autoreleasepool {
Fraction *fractionA = [Fraction new];
Fraction *fractionB = [Fraction new];

[fractionA setTo:10 over:406];
[fractionB setTo:23 over:901];

[fractionA print];
[fractionB print];
}
return 0;
}

编译运行,我们得到如下的结果:

[img]http://dl.iteye.com/upload/attachment/0078/8355/16d6bf59-3a64-3cef-921b-ad5825b9e48d.png[/img]

带有多个参数的方法在定义时,参数名称是可选的,比如上面的方法我们还可以定义为如下形式:-(int) set: (int) n: (int) d;显然这里没有对第二个参数命名,那么调用该方法时,我们可以这样做[fractionA set: 10: 406],虽然可以这么做,但是省略参数名的做法是不推荐的,因为可能会引起语义不清等问题。如果参数很多或者参数很重要,可能就会引起大问题。
[url=http://sarin.iteye.com/blog/1763111]接下文[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值