Objective-C 2.0 学习笔记五(类)

变更履历

版本:v1.0

介绍

OK,这一部分是类的学习,以及如何编写方法,是的,我们之前学过如何创建方法,在这里,我们将为方法添加更多的参数,下面我们就开始吧。

分离接口和实现文件

我们知道,一个类包含两部分定义,@interface 和 @implementation,这两部分其实可以分成独立的文件存储,我们将创建两个独立的文件 Fraction.h 和 Fraction.m。@interface 位于 Fraction.h 文件中;@implementation 位于 Fraction.m 文件中。

接口文件 Fraction.h

//
// Fraction.h
// FractionTest
//
// Created by Steve Kochan on 9/29/10.
// Copyright (c) ClassroomM, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
// The Fraction class
@interface Fraction : NSObject
{
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
-(double) convertToNum;
@end

接口文件告诉编译器 Fraction 类的外观特征。

实现文件 Fraction.m

//
// Fraction.m
// FractionTest
//
// Created by Steve Kochan on 9/29/10.
// Copyright (c) ClassroomM, Inc. All rights reserved.
//
#import "Fraction.h"

@implementation Fraction
-(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

实现文件用来实现 Fraction 类的实现细节。import "Fraction.h" 用来将接口文件导入到实现文件中。我们注意到 import 这里使用的是双引号,而不是 import <Foundation/Foundation.h> 的尖括号。双引号用于本地文件(我们自己创建的文件)。

测试程序 FractionTest.m

#import "Fraction.h"

int main (int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    Fraction *myFraction = [[Fraction alloc] init];
    // set fraction to 1/3
    [myFraction setNumerator: 1];
    [myFraction setDenominator: 3];
    // display the fraction
    NSLog (@"The value of myFraction is:");
    [myFraction print];
    [myFraction release];
    [pool drain];
    return 0;
}
我们注意到 FractionTest.m 中并没有导入实现文件。

合成存取器

在编写 Java 代码时,一个类的属性一般都会有对应的 getter/setter 方法,一般称为存取方法。OC 2.0 提供了一种简便的方式可自动生成存取方法,它是由 @property @synthesize 两个关键字配合完成的。

@interface Fraction : NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) print;
-(double) convertToNum;
@end
这里我们并没有为 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
下面这行内容告诉 OC 编译器,为两个实例变量(numerator 和 denominator)生成对应的存取方法:

@synthesize numerator, denominator;
通常,存储方法以 set 开头,获取方法以 get 开头,例如 getNumerator、setNumerator。

使用点运算符访问属性

点运算符(.)在 Java 中很常见,可以用来f访问除私有限定之外的属性和方法,但在 OC 中,目前为止,点运算符只能用来访问属性,这个实在没啥值得说的,[ program ] 这个方式有些邪恶啊。

多个参数的方法

好了,我们的方法终于可以有多个参数了,说实话,OC 中这种定义方法参数的方式挺让人不适用的,调用时,弄得代码老长,你说这可读性是提高了呢?还是降低了呢?好了,言归正传。

一个同时设置 numerator 和 denominator 的方法可以命名为 setNumerator:andDenominator,形式如下:

[fraction setNumerator: 1 andDenominator: 3];
[fraction setTo: 1 over: 3];

上面两行代码的区别只在于命名方式,很难说哪个更好,我自己一般用第一种。我们来看看这是如何定义的:

#import <Foundation/Foundation.h>
// Define the Fraction class
@interface Fraction : NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) print;
-(void) setTo: (int) n over: (int) d;
-(double) convertToNum;
@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, char *argv[])
{
    Fraction *aFraction = [[Fraction alloc] init];
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    [aFraction setTo: 100 over: 200];
    [aFraction print];
    [aFraction setTo: 1 over: 3];
    [aFraction print];
    [aFraction release];
    [pool drain];
    return 0;
}

不带参数名得方法

上面的缺点是,当一个方法参数很多时,可读性较差,所以 就有了另外一种编写方式:

-(int) set: (int) n: (int) m

调用时是这样写的:

[fraction set 1 : 3];

说实话,这种省略真不咋地,很难知道这个调用在做些什么。

局部变量

方法的参数和方法中定义的变量都是局部变量。对于方法参数来说,通过方法传递的任何参数都被复制到局部变量中。因为方法使用参数的副本,所以不能改变通过方法传递的原值。当然,如果参数是对象,那么是可以更改其中实例变量值的。

static 关键字

用 static 声明的变量只在程序开始执行时初始化一次。

static int hitCount = 0;
值得注意的是,OC 中的静态变量是可以用在非静态方法中的,这与 Java 是不同的。

self 关键字

self 与 java 的 this 关键字含义是一样的,但 this 在有些情况下是省略的,而 self 却不行,如方法调用:

- (void) add: (Fraction *) f
{
    // To add two fractions:
    // a/b + c/d = ((a*d) + (b*c)) / (b * d)
    numerator = numerator * f.denominator + denominator * f.numerator;
    denominator = denominator * f.denominator;
    [self reduce];
}

在方法中分配和返回对象

直接上代码:

-(Fraction *) add: (Fraction *) f
{
    // To add two fractions:
    // a/b + c/d = ((a*d) + (b*c)) / (b * d)
    // result will store the result of the addition
    Fraction *result = [[Fraction alloc] init];
    result.numerator = numerator * f.denominator + denominator * f.numerator;
    result.denominator = denominator * f.denominator;
    [result reduce];
    return result;
}

上面的代码存在内存泄露的问题。这里涉及 cocoa 内存管理机制,具体请参考《 iOS 内存管理编程指南》中的描述。





你可能感兴趣的:(java,cocoa,Class,import,interface,编译器)