一、实例变量可见度
可见度 特点
public 实例变量可以在类的外部和内部操作
protected 实例变量只能在该类和其子类内操作 默认
private 实例变量只能在该类内访问
内部:相应类的@implementation和@end之间
@interface Person : NSObject
{
@public
NSString*_name;
@protected
NSString*_gender;
int_age; //年龄
@private
NSString*_age;
}
mian.m文件中使用
Person * p = [[Person alloc] init];
p->_name = @"zhangyixing";
// p->_gender = @‘m‘; // 警告
// p->_age = 18; // 警告
为什么不使用@public 暴露细节 不符合封装
在其他文件访问@protected修饰的实例变量-----方法
提示:添加两个方法。
赋值:通过方法传入参数,在类的内部实现实例变量赋值。
取值:通过方法获取实例变量的值。
二、方法--方法类型、返回值类型、方法名、参数列表
OC中的方法------类方法、实例方法
同一个中,所有的类方法中不能出现重名 所有的实例方法中不能出现重名
1、 类方法:只能类使用 [类名 类方法名]
在类方法中不能使用实例变量 调用类方法时没有创建对象
声明-----Person.h
+ (void)sayHi;
实现-----Person.m
+ (void)sayHi
{
NSLog(@"hi");
}
2、实例方法:只能对象使用 [对象 实例方法名]
声明-----Person.h
- (void)sayHello;
实现-----Person.m
- (void)sayHello
{
NSLog(@"hello");
}
3、声明方法 (返回值类型)没有参数只写方法名
(1)无返回值、无参数
- (void)sleep;
实现
- (void)sleep
{
NSLog(@"sleep");
}
使用
[p sleep];
(2)无返回值、有参数
语法--- :(参数类型)参数名
参数以:开头 ":"标识参数,不能省略。有冒号必须有参数
///// 一个参数
- (void)eat:(NSString *)food;
实现
- (void)eat:(NSString *)food
{
NSLog(@"%@",food);
}
使用
[p eat:@"beef"];
///// 两个参数
- (void)setName:(NSString *)name age:(NSInteger)age; // 赋值
实现
- (void)setName:(NSString *)name age:(NSInteger)age
{
_name = name;
_age = age;
// name和age是方法的形参,接收从外部传入的值
}
使用
[p setName:@"zhangyixing" age:18];
(3) 有返回值、无参数
- (NSString *)getName; // 取值
实现
- (NSString *)getName
{
return _name;
}
使用
NSLog(@"name=%@",[p getName]);
// 方法名使用驼峰命名法---方法名: setName:age:
首字母小写;第一个参数修饰符首字母大写;
第二个首字母小写;都使用驼峰命名法
4、方法使用----[person sayHi];
在OC中没有”student调用sayHi“这种表述。
在OC中使用消息发送机制:[receiver message]。
正确表述:给student对象发送sayHi消息。
1)student接收到消息,即方法sayHi;
2)student找到sayHi方法,并执行。
三、setter、getter
1、简述
在OC里,为实例变量赋值的方法称作setter(设置器)。
读取实例变量值的方法称作getter(访问器)。
我们之前写的那些赋值取值的方法都可以称作setter和getter。
2、实例
(1)设置_name实例变量的值
// setter方法是实例方法,没有返回值,只有一个参数
// 方法名 set + 实例变量名(忽略_,使用驼峰命名法)
// 参数 跟操作的实例变量有关 类型跟操作的实例变量一致 实例变量名(忽略_)
- (void)setName:(NSString *)name;
实现
- (void)setName:(NSString *)name
{
_name = name;
// name是方法的形参,接收从外部传入的值 _name实例变量
}
(2)访问实例变量
// getter是实例方法 没有参数 返回值类型与操作的实例变量保持一致
// 方法名 实例变量名(忽略_) 切记:不要以get开头
- (NSString *)name;
实现
- (NSString *)name
{
return _name;
}
(3)使用
// 使用setter方法给Person对象的实例变量_name赋值
[p setName:@"zhang"];
// 使用getter方法读取实例变量的值
NSLog(@"name = %@", [p name]);
3、与实例变量的关系
无论setter还是getter内部操作的是实例变量
每个实例变量都需要一对setter和getter方法
4、main.m文件中使用
// 使用setter方法给Person对象的实例变量_name 和_age赋值
[p setName:@"zhang"];
[p setAge:23];
// 使用getter方法读取实例变量的值
NSLog(@"name = %@, age = %ld", [p name], [p age]);
四、自定义初始化方法
-(id)init这个初始化方法只能给实例变量设置默认值,不灵活
- (id)init
{
return self;
}
-(id)initWithName:自定义初始化法,根据需求定义初始化方法
// 自定义初始化方法 初始化对象时给_name和_age赋值
- (id)initWithname:(NSString *)name age:(NSInteger)age;
实现
- (id)initWithname:(NSString *)name age:(NSInteger)age
{
// 对象初始化时可以传入姓名和年龄 将传入的值赋值给实例变量
_name = name;
_age = age;
return self;
}
main.m文件中使用
Person * p3 = [[Person alloc] initWithname:@"zhangyixing" age:18];
Person * p4 = [[Person alloc] initWithname:@"liyifeng" age:20];
NSLog(@"name=%@",[p3 name]);
[p4 setName:@"liminhao"];
NSLog(@"name=%@",[p4 name]);
五、导入文件
1、#import导入头件,即:导入头件中的内容到当前类。
#import “”导入自定义类,自己创建的文件 从当前工程目录开始查询
#import <> 导入类库中的头文件,自己创建的文件 从当前工程目录开始查询
功能类似C语言中的#include,但是可以避免头文件被重复导入。
容易出现循环导入头文件问题。
2、#include 和 #import的区别
(1)include不能重复导入同一个文件
(2)import可以重复导入同一个文件
3、@class
#import可能会造成循环导入头文件问题,需要使用@class解决
@class的作用,告知编译器系统class后面的标识符可以作为一个类名使用;并没有导入这个类的内容
使用@class可以解决循环导入头文件的问题。
如果需要在类的接口部分使用其他类型:
1)在.h文件中,使用@class声明需要使用的类型;
2)在.m文件中,使用#import导入需要使用的类型
实例
创建Man、Woman、Child三个类并完成声明与实现部分
新创建Family类
Family.h文件
#import <Foundation/Foundation.h>
// 使用@class“导入”文件
@class Man;
@class Woman;
@class Child;
@interface Family : NSObject
// 定义实例变量
{
Man * _father;
Woman * _mother;
Child * _kid;
}
// 初始化方法设置father和mother
- (id)initWithFather:(Man *)father mother:(Woman *)mother;
// 声明setter、getter方法
- (void)setFather:(Man *)father;
- (Man *)father;
- (void)setMother:(Woman *)mother;
- (Woman *)mother;
- (void)setKid:(Child *)kid;
- (Child *)kid;
// 声明一般方法
- (void)introduce;
Family.m文件
#import "Family.h"
导入文件
#import "Man.h"
#import "Woman.h"
#import "Child.h"
@implementation Family
// 初始化方法设置father和mother
- (id)initWithFather:(Man *)father mother:(Woman *)mother
{
_father = father;
_mother = mother;
return self;
}
// 实现setter、getter方法
- (void)setFather:(Man *)father
{
_father = father;
}
- (Man *)father
{
return _father;
}
- (void)setMother:(Woman *)mother
{
_mother = mother;
}
- (Woman *)mother
{
return _mother;
}
- (void)setKid:(Child *)kid
{
_kid = kid;
}
- (Child *)kid
{
return _kid;
}
// 实现一般方法
- (void)introduce
{
NSLog(@"father:%@,mother:%ld,kid:%@", [_father name], [_mother age], [_kid gender]);
}
main.m文件
#import <Foundation/Foundation.h>
// 导入文件
#import "Man.h"
#import "Woman.h"
#import "Child.h"
#import "Family.h"
Man * m = [[Man alloc] initWithName:@"zhangjiashuai"];
Woman * w = [[Woman alloc] initWithName:@"zhangjiamei" age:18];
Family * f = [[Family alloc] initWithFather:m mother:w];
Child * c = [[Child alloc] initWithName:@"zhangyi" gender:@"m"];
[f setKid:c];
[f introduce];
六、总结
1、实例变量有3种常见的可见度:@public、@protected、@private。
@public违背了封装特性,面向对象开发中很少使用;
@protected默认可见度,自己和子类中能使用—>访问实例变量;
@private自己类中能使用—>访问实例变量。
2、方法是OC的核心,采用消息机制:[receiver message]。
“-”message由对象来调用;
“+”message由类来调用。