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

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

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

    来看下头文件中的类定义:
//
//  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中运行代码,我们就得到如下的结果:

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

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

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

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

    带有多个参数的方法在定义时,参数名称是可选的,比如上面的方法我们还可以定义为如下形式:-(int) set: (int) n: (int) d;显然这里没有对第二个参数命名,那么调用该方法时,我们可以这样做[fractionA set: 10: 406],虽然可以这么做,但是省略参数名的做法是不推荐的,因为可能会引起语义不清等问题。如果参数很多或者参数很重要,可能就会引起大问题。
    接下文

你可能感兴趣的:(Objective-C)