目录
V. 面向对象
V-I 类与对象
- 类:是某一批对象的抽象,可以把类理解成某种概念;
- 对象:是一个具体存在的实体。
- 二者联系:
- 类是模版,类的对象是根据模版创建出来的
- 类模版中有什么,对象中就有什么
1. 定义类
a. 关键字:@interface 、 @end、@implementation
b. 继承:NSObject
- 类的三要素:a. 名称 b. 这类事物的特征 c.这类事物具有的共同行为
- 定义类的语法:
1. 位置:直接写在源文件中,不用写在main函数中
2. 类的定义:- 类的声明:
@interface 类名: NSObject{
这类事物具有的共同特征,将他们定义为变量
}
功能就是一个方法,将方法的声明写在这里
@end
- 类的实现
@implementation 类名
将方法的实现写在这里
@end
#import <Foundation/Foundation.h>
@interface Person:NSObject{
NSString *_name;//*以_开头
int _age;
float _height;
}
@end
@implementation Person
@end
int main(int argc, const char * argv[]) {
...
return 0;
}
- 注意
- 类必须要有声明和实现
- 类名的第一个字母必须要以大写开头
- 用来表示类的特征的变量必须写在@interface的大括号之中
- 定义属性时,要以下划线开头
2. 对象的产生和使用
- 创建对象语法格式:
[[类名 alloc] 初始化方法];
其中alloc是Objective的关键字,负责为该类分配内存空间、创建对象。因为所有对象都继承了NSObject类,所以有默认初始化方法:init。 - 类定义变量语法格式:
类名 * 变量名;
- 通过对象访问成员变量(访问权限允许):
对象->成员变量名
3. 对象与指针
eg:FKPerson *person = [[FKPerson alloc] init];
FKPerson*类型的变量本质是一个指针变量,所以person变量保存了FKPerson对象在内存中的首地址,它被保存在main()函数的的动态存储区,而真正的FKPerson对象放在堆内存中。
Objective-C不允许直接访问堆内存中的对象,只能通过该对象的指针变量来访问该对象。
4. self关键字
`self`关键字总指向该方法的调用者,当self出现在实例方法中时,self代表调用该方法的对象;self出现在类方法中时,self代表调用该方法的类
==作用==:让类中的一个方法访问该类的另一个方法或成员变量
5. id类型
id类型可以代表所有对象的类型,也就是说任何类的对象都可以赋值给id类型的变量
id p = [Person new];// p = [[Person alloc] init];
V-II 方法详解
1. 方法的所属性
方法是类或对象的行为特征的抽象,从功能上看,方法完全类似于传统结构化程序设计中的函数。
在结构化编程语言里,软件是由一个个函数组成的,是一等公民;而在面向对象的编程语言中。类是一等公民。因此,在OC中,方法不能独立存在,方法必须属于类或语言。
- 定义方法:不能单独定义一个方法,只能在类体中定义。其中若方法使用+标识符,那么这个方法就属于这个类;若使用-标识符,则属于这个类的实例
- 调用:不能独立调用方法,执行方法时必须使用类或对象来作为调用者即
[类 方法]
或[对象 方法]
2. 形参个数可变的方法
如果在定义方法时,在最后一个形参名后添加,...
,则表明该形参可以接受多个参数;注意:个数可变的形参只能处于形参列表的最后
#import<foundation/foundation.h>
@interface VarArgs : NSObject
- (void)test : (NSString *) name,...;//可接受个数可变的NSString *参数
@end
- 关键字
va_list
:是一个类型,用于定义指向可变参数列表的指针变量va_start
:是一个函数,指定开始处理可变形参的列表,并让指针变量指向可变形参列表的第一个参数va_end
:结束处理可变形参,释放指针变量va_arg
:是一个函数,返回获取指针当前指向的参数的值,并将指针移向下一个参数
#import "VarAegs.h"
@implementation VarArgs
- (void) test: (NSString *)name,...{
va_list argList;//定义一个va_list类型指针变量
if(name){//判断第一个参数是否存在
NSLog(@"%@", name);
va_start(argList, name);//使argList指向name列表的的第一个参数,开始提取可变参数列表的参数
NSString *arg = va_arg(argList, id);//用于保存当前获取的参数,如果该参数不为NULL则进入循环体
while(arg){
NSLog(@"%@", arg);
arg = va_arg(argList, id);//提取参数并指向下一个
}
va_end(argList);//释放argList指针,结束
}
}
@end
int main(){
@autoreleasepool {
VarArgs *va = [[VarArgs alloc] init];
[va test: @"hello" @"world",NULL];
}
}//输出为“helloworld”
V-III 成员变量
根据定义位置的不同,可分为:成员变量、局部变量和全局变量
1. 成员变量及其运行机制
成员变量是指在接口部分或类实现部分定义的变量,OC中的成员变量都是实例变量;实例变量是从该类的实例被创建开始起存在,作用域与对应的实例的生存范围相同
从内存存储的角度,OC的对象与C中结构体类似
- 语法:
实例->实例变量
#import <Foundation/Foundation.h>
@interface Person : NSObject{
@public//封装的访问控制符
NSString *_name;//定义实例变量
int _age;
}
@end
@implementation Person
@end
int main(){
@autoreleasepool {
Person *p = [[Person alloc] init];//创建FKPerson对象,并通过指针访问其中的实例变量
NSLog(@"name:%@ age:%d", p->_name, p->_age);
p->_age = 10;
p->_name = @"Objective-C";
NSLog(@"name:%@ age:%d", p->_name, p->_age);
}
return 0;
}//输出结果:NULL 0
Objective-C 10
上面的实例中,成员变量无需初始化,系统会默认初始化,基本类型的实例变量默认初始化为0;指针类型的成员变量默认初始化为NULL
2. 模拟类变量
通过内部全局变量来模拟类变量
#import <Foundation/Foundation.h>
@interface User : NSObject
+ (NSString*) nation;
+ (void) setNation:(NSString *) newNation;
@end
//实现
static NSString * nation = nil;//定义一个static修饰的全局变量
@implementation User
+ (NSString*) nation{
return nation;//返回nation全局变量
}
+ (void) setNation:(NSString *)newNation{
//对nation全局变量赋值
if(![nation isEqualToString:newNation])
{
nation = newNation;
}
}
@end
int main() {
@autoreleasepool {
//为User类变量赋值
[User setNation:@"People"];
NSLog(@"User 的 nation 类变量为:%@",[User nation]);//访问User的类变量
}
return 0;
}
- 注意:OC中的static关键字不能用于修饰成员变量,只能修饰局部变量、全局变量和函数。其中 static修饰局部变量表示将该局部变量存储到静态存储区;static修饰全局变量限制该全局变量只能在当前源文件中访问;static修饰函数限制该函数只能在当前源文件中调用
3. 单例模式
V-IV 隐藏和封装
1. 理解封装
封装是面向对象的三大特性之一(继承和多态),是指将对象的状态和信息隐藏在对象内部,不允许外部程序直接访问对象内部的信息,而是通过该类所提供的方法来实现对内部信息的操作和访问
目的:
- 隐藏类的实现细节
- 让使用者只能通过实现预定的方法访问数据,可在方法中加入控制逻辑(比如说年龄一般不超过140岁,月份不超过12月),限制对成员变量不合理的访问
- 可进行数据检查,从而有利于保证对象信息的完整性
- 便于修改,提高代码可维护性
考虑的方面:
- 把对象的成员变量和实现细节隐藏起来,不允许外部直接访问
- 把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作
2. 使用访问控制符
优先级
- @private(当前类访问权限):成员变量只能在当前类的内部访问;其用于彻底隐藏成员变量
- @package(相同映像访问权限):成员变量可以在当前类以及当前类的同一个映像的任意地方访问;其用于部分隐藏成员变量
- @protected(子类访问权限):成员变量可以在当前类、当前子类的任意地方访问;其用于部分暴露成员变量
- @public(公共访问权限):成员变量可以在任意地方访问
Tips
1.#import
- 是一个预处理命令
- 作用:相当于C语言中的#include,是#include指令的增强版
- 与#include的区别:同一个文件无论#import多少次,只会包含一次
- 原理:#import指令在包含文件时,底层会先判断这个文件是否被包含,如果包含则直接跳过。
2.NSLog函数
- 作用:相当于C语言中的printf,是printf函数的增强版
- 语法:
NSLog(@"一个字符串直接量")
- 与printf区别:
a. 在输出完信息后,会自动换行
b. 不仅可以输出字符串,也可以输出整数、C风格字符串和Objective-C对象
c. 输出调试相关信息(时间、程序名称、进程编号、线程编号、输出信息)
3.NSString函数
- NSString类型的指针变量专门用来存储OC字符串的地址
a. OC字符串常量必须要用到一个前缀@符号:
"jack"
是C语言字符串
@“jack”
是OC字符串常量
b.NSString *str = @"jack"
指针类型
c. 要使用NSLog函数输出OC字符串的值则用%@占位符