一、封装
1、set方法和get方法
1.1、set方法和get方法的使用场合
使用@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数。
1.2、set方法
作用:用来设置成员变、量,可以在方法里面过滤掉一些不合理的值
命名规范:方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写;
形参名称不要跟成员变量同名;
返回值一定是void,后面一定要接收一个参数,而且参数类型跟成员变量类型一致;
形参的名称不能跟成员变量名一样。
1.3、get方法
作用:返回对象内部的成员变量
命名规范:get方法的名称一般就跟成员变量同名;
肯定有返回值;
不需要接收任何参数。
1.4、成员变量的命名规范
成员变量;都以下划线 _开头
可以跟get方法的名称区分开
可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量。
1.5、封装的作用
过滤不合理的值
屏蔽内部的赋值过程
让外界不必关注内部的细节
1.6、程序示例及结果显示
<span style="font-size:18px;"><span style="font-size:18px;">#import<Foundation/Foundation.h>
@interface Student : NSObject
{
int _cScore;
int _ocScore;
int _sumScore; // 总分只读
double _averageScore; // 平均分只读
}
- (void) setCScore:(int)cScore;
- (int) cScore;
- (void) setOcScore:(int)ocScore;
- (int) ocScore;
- (int) sumScore;
- (double) averageScore;
@end
@implementation Student
- (void) setCScore:(int)cScore
{
_cScore = cScore;
_sumScore = _cScore + _ocScore;
_averageScore = _sumScore/2;
}
- (int) cScore
{
return _cScore;
}
- (void) setOcScore:(int)ocScore
{
_ocScore = ocScore;
_sumScore = _cScore + _ocScore;
_averageScore = _sumScore/2;
}
- (int) ocScore
{
return _ocScore;
}
- (int) sumScore
{
NSLog(@"总分是%d",_sumScore);
}
- (double) averageScore
{
NSLog(@"平均分是%f",_averageScore);
}
@end
int main()
{
Student *s = [Student new];
[s setCScore:90];
[s setOcScore:80];
[s sumScore];
[s averageScore];
}</span></span>
2、弱语法
尽管编译器容错能力比较,但是写代码必须规范,一旦运行过程中出错,就会闪退。
常见警告:-[Persontest]: unrecognized selector sent to instance 0x7fd2ea4097c0。分析:给Person对象发送了一个不能识别的消息:test。
OC是在运行过程中才会检测对象有没有实现相应的方法
3、类方法
说明:直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)
3.1、类方法和对象方法对比
对象方法:
以减号-开头
只能让对象调用,没有对象,这个方法根本不可能被执行
对象方法能访问实例变量(成员变量)
类方法:
以加号+开头
只能用类名调用,对象不能调用
类方法中不能访问实例变量(成员变量)
使用场合:当不需要访问成员变量的时候,尽量用类方法
类方法和对象方法可以同名
3.2示例程序和运行结果
<span style="font-size:18px;"><span style="font-size:18px;">/*
设计一个计算器类
* 求和
* 求平均值
*/
#import <Foundation/Foundation.h>
// 工具类:基本没有任何成员变量,里面的方法基本都是类方法
@interface JiSusnQi : NSObject
+ (int)sumOfNum1:(int)num1 andNum2:(int)num2;
+ (int)averageOfNum1:(int)num1 andNum2:(int)num2;
@end
@implementation JiSusnQi
+ (int)sumOfNum1:(int)num1 andNum2:(int)num2
{
return num1 + num2;
}
+ (int)averageOfNum1:(int)num1 andNum2:(int)num2
{
int sum = [JiSusnQi sumOfNum1:num1 andNum2:num2];
return sum / 2;
}
@end
int main()
{
int a = [JiSusnQi averageOfNum1:10 andNum2:12];
NSLog(@"a=%d", a);
// JiSusnQi *jsq = [JiSusnQi new];
//
//
// [jsq sumOfNum1:10 andNum2:13];
return 0;
}</span></span>
4、self关键字
4.1、出现的地方
所有的OC方法中(对象方法\类方法),不能出现在函数
4.2、self的用途:
说明:谁调用了当前方法,self就代表谁;self出现在对象方法中,self就代表对象;self出现在类方法中,self就代表类。
在对象方法利用"self->成员变量名"访问当前对象内部的成员变量。
[self方法名]可以调用其他对象方法\类方法。
使用"self->成员变量名"访问当前方法调用的成员变量。
使用"[self方法名];"来调用方法(对象方法\类方法)。
4.3、常见错误
用self去调用函数;类方法中用self调用对象方法,对象方法中用self调用类方法;self死循环
4.4、程序示例和结果
二、继承
说明:基本上所有类的根类是NSObject。
1、继承的作用
抽取重复代码;
建立了类之间的关系;
子类可以拥有父类中的所有成员变量和方法。
2、继承的使用场合
当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类
当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类
3、重写
子类重新实现父类中的某个方法,覆盖父类以前的做法4、super
super的作用:直接调用父类中的某个方法;super处在对象方法中,那么就会调用父类的对象方法; super处在类方法中,那么就会调用父类的类方法。使用场合:子类重写父类的方法时想保留父类的一些行为。
5、注意点
父类必须声明在子类的前面。子类不能拥有和父类相同的成员变量。
调用某个方法时,优先去当前类中找,如果找不到,去父类中找。
6、缺点
耦合性太强。父类丢失,子类就无法使用。7、程序示例和运行结果
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">#import <Foundation/Foundation.h>
// Person
@interface Person : NSObject
{
int _age;
}
- (void)setAge:(int)age;
- (int)age;
- (void)run;
+ (void)test;
@end
@implementation Person
+ (void)test
{
NSLog(@"Person+test");
}
- (void)run
{
NSLog(@"person---跑");
}
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
@end
// 不允许子类和父类拥有相同名称的成员变量
// Student
@interface Student : Person
{
int _no;
// int _age;
}
+ (void)test2;
@end
@implementation Student
// 重写:子类重新实现父类中的某个方法,覆盖父类以前的做法
- (void)run
{
NSLog(@"student---跑");
}
+ (void)test2
{
[self test];
}
@end
int main()
{
[Student test2];
// Student *s = [Student new];
//
// [s run];
return 0;
}</span></span></span>
三、多态性
1、基本概念
某一类事物的多种形
OC对象具有多态性
2、代码的体现
父类类型的指针指向子类对象
Person *p = [Student new];
p->age =100;
[p walk];
子类对象赋值给父类指针
父类指针访问对应的属性和方法
3、多态的好处
用父类接收参数,节省代码
如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
4、多态的局限性
不能访问子类的属性(可以考虑强制转换)
即父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法
5、多态的细节
动态绑定:在运行时根据对象的类型确定动态调用的方法
6、程序示例及运行结果
<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"> #import <Foundation/Foundation.h>
// 动物
@interface Animal : NSObject
- (void)eat;
@end
@implementation Animal
- (void)eat
{
NSLog(@"Animal-吃东西----");
}
@end
// 狗
@interface Dog : Animal
- (void)run;
@end
@implementation Dog
- (void)run
{
NSLog(@"Dog---跑起来");
}
- (void)eat
{
NSLog(@"Dog-吃东西----");
}
@end
// 猫
@interface Cat : Animal
@end
@implementation Cat
- (void)eat
{
NSLog(@"Cat-吃东西----");
}
@end
// 这个函数是专门用来喂动画
//void feed(Dog *d)
//{
// [d eat];
//}
//
//void feed2(Cat *c)
//{
// [c eat];
//}
//
// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
[a eat];
}
int main()
{
// NSString *d = [Cat new];
// [d eat];
/*
Animal *aa = [Dog new];
// 多态的局限性:父类类型的变量 不能 用来调用子类的方法
//[aa run];
// 将aa转为Dog *类型的变量
Dog *dd = (Dog *)aa;
[dd run];
*/
Dog *d = [Dog new];
[d run];
/*
Animal *aa = [Animal new];
feed(aa);
Dog *dd = [Dog new];
feed(dd);
Cat *cc = [Cat new];
feed(cc);
*/
/*
// NSString *s = [Cat new];
Animal *c = [Cat new];
NSObject *n = [Dog new];
NSObject *n2 = [Animal new];
// 多种形态
//Dog *d = [Dog new]; // Dog类型
// 多态:父类指针指向子类对象
Animal *a = [Dog new];
// 调用方法时会检测对象的真实形象
[a eat];
*/
return 0;
}</span></span></span>
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------