OC类和对象

Posted Billy Miracle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC类和对象相关的知识,希望对你有一定的参考价值。

定义类

  • 接口部分:定义该类包含的成员变量和方法。
  • 实现部分:为该类的方法提供实现。

在这里插入图片描述
成员变量:用于描述该类的对象的状态数据。
方法:用于描述该类的行为。
在这里插入图片描述

  • 类型:可以是OC允许的任何数据类型。
  • 成员变量名:建议以下划线开头,如:_name。
  • 方法类型标识符:+代表类方法,直接用类名调用,-代表实例方法,必须用对象调用。
  • 方法返回值类型:可以是OC允许的任何数据类型。
  • 方法签名关键字:由方法名、形参标签和冒号组成。

方法类似于我们之前熟悉的函数,区别之处在于所有类型应该用圆括号括起来。另外,要注意冒号,有 : 代表方法有参数。
在这里插入图片描述

  • 类实现部分的类名必须与类接口部分的类名相同。
  • 类实现部分也可以声明自己的成员变量,但只能在当前类里访问。
  • 类实现部分必须为类声明部分的每个方法提供方法定义。

分离接口和实现文件

通常,类的声明(@interface部分)放在它名为 class.h 的文件中,而类的定义(@implementation部分)放在相同名称的文件中,但拓展名要使用.m。
示例:
Fraction.h接口文件

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

@interface Fraction : NSObject

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

@end

NS_ASSUME_NONNULL_END

Fraction.m实现文件

#import "Fraction.h"

@implementation Fraction {
    int numerator;
    int denominator;
}
-(void) print {
    NSLog(@"%i/%i",numerator,denominator);
}
-(void) setNumerater: (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

main.m主测试程序

#import "Fraction.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Fraction *myFraction = [[Fraction alloc] init];
        [myFraction setNumerater: 1];
        [myFraction setDenominator: 3];
        NSLog(@"The value of myFraction is:");
        [myFraction print];
        NSLog(@"The value of myFraction is: %lf",[myFraction convertToNum]);
    }
    return 0;
}

对象和指针

在上面的Fraction *myFraction = [[Fraction alloc] init];这段代码中,创建了一个Fraction对象,这个对象被赋给myFraction变量。其实,myFraction变量仅仅保存了Fraction对象在内存中的首地址。注意:如果堆内存里的对象没有任何变量指向它,那么程序将无法再访问该对象。

static关键字

在变量声明前加上关键字static,可以使局部变量保留多次调用一个方法所得的值。
例如:static int hitCount = 0;

self关键字

self关键字总是指向该方法的调用者(对象或类),当self出现在实例方法中时,self代表调用该方法的对象;当self出现在类方法中时,self代表调用该方法的类。
self关键字最大的作用是让类中的一个方法访问该类的另一个方法或成员变量。
例子:

//  FKDog.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKDog : NSObject
-(void) jump;
-(void) run;
@end

NS_ASSUME_NONNULL_END

//  FKDog.m

#import "FKDog.h"

@implementation FKDog

-(void) jump {
    NSLog(@"正在执行jump方法");
}
/*
-(void) run {
    FKDog* d = [[FKDog alloc] init];
    [d jump];
    NSLog(@"正在执行run方法");
}
如果不使用self关键字,则要用以上程序来实现。
*/
-(void) run {
    [self jump];
    NSLog(@"正在执行run方法");
}

@end

//  main.m

#import "FKDog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        FKDog* dog = [[FKDog alloc] init];
        [dog run];
    }
    return 0;
}

大家可以自己尝试一下程序的输出结果。
在局部变量与成员变量重名时也可以使用self关键字进行区分。
示例:

//  FKWolf.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKWolf : NSObject {
    NSString* _name;
    int _age;
}
-(void) setName: (NSString*) _name andAge: (int) _age;
-(void) info;

@end

NS_ASSUME_NONNULL_END

//  FKWolf.m
#import "FKWolf.h"

@implementation FKWolf

-(void) setName:(NSString *)_name andAge:(int)_age{
    self->_name = _name;
    self->_age = _age;
}
-(void) info {
    NSLog(@"我的名字是%@,年龄是%d岁",_name,_age);
}
@end

//main.m
#import "FKWolf.h"

int main(int argc, const char* argv[]) {
    @autoreleasepool {
        FKWolf *w = [[FKWolf alloc] init];
        [w setName:@"小灰" andAge:8];
        [w info];
    }
    return 0;
}

id类型

OC提供了一个id类型,任意类的对象都可以赋值给id类型的变量。当通过id类型的变量来调用方法时,OC将会执行动态绑定,它会在运行时判断该对象所属的类,并在运行时确定需要动态调用的方法。
示例:
将上一个程序稍作修改。

//main.m
#import "FKWolf.h"

int main(int argc, const char* argv[]) {
    @autoreleasepool {
    	//使用id
        id w = [[FKWolf alloc] init];
        [w setName:@"小灰" andAge:8];
        [w info];
    }
    return 0;
}

以上是关于OC类和对象的主要内容,如果未能解决你的问题,请参考以下文章

ios开发之OC基础-类和对象

iOSDay10OC类和对象

oc知识点 类和对象

OC面向对象—继承

OC类和对象

OC学习--类和对象的关系