黑马程序员_OC面向对象的三大特性
来源:互联网 发布:一个域名成就一个梦想 编辑:程序博客网 时间:2024/06/05 13:31
OC语言中面向对象有三大特性,分别是封装,继承和多态。
(一)封装:
在上次的笔记中,我学到了类的成员变量有四种作用域类型,分别是@public,@private,@protected和@package。
之前我们定义好成员变量后,想要在main中直接访问成员变量,往往要在成员变量的定义时候加上一个@public,这种
做法虽然可以实现访问,可是它会让你的数据变得很透明,不仅可以随意被访问而且有可能会变得很不合理,例如我顶
一个一个int类型的age年龄属性,在主函数main中把age赋值成-10,这都是可以的。所以,为了保证数据的不透明习
惯,安全性和合理性。我们一般不适用@Public来使得外界获得访问权利。而是提供一种封装方法来供外界使用访问我
们内部的成员变量。这些方法成为setter和getter。它们就是我们的封装。
1.setter和getter的声明:
<div style="text-align: justify;"><span style="font-size:18px; font-family: Arial, Helvetica, sans-serif;">@interface Person : NSObject</span></div><span style="font-size:18px;">{ int _age;}</span><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">t)age;- (int)age;@end</span></div>- (void)setAge:(i<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">n</span></div>
由上我们可以总结setter和getter的声明规范和一些注意点。首先,setter是更改成员变量属性,所以不需要返回值并且
一定要传入一个和成员变量数据类型相同的参数。同时遵循方法命名规范:一个参数一个分号,数据类型用小括号括起
来。而getter的作用是获得成员变量的值,所以不需要传入参数,并且一定有返回值,返回值为成员变量的数据类型。
我们定义的成员变量是已下滑线开头的,它相应的getter和setter则不需要下划线。
2.setter和getter的实现:
<div style="text-align: justify;"><span style="font-size:18px; font-family: Arial, Helvetica, sans-serif;">#import "Person.h"</span></div><span style="font-size:18px;"></span><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">@implementation Person</span></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">- (void)setAge:(int)age</span></div>{ if (age<=0)<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"> _age = age; </span></div> age = 1; }- (int)age{<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">end</span></div> return _age;}<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">@</span></div>
由上我们可以总结setter和getter方法的实现规范。它们可以依靠代码来实现访问或者修改我们的内部成员变量的值。基
本上,每定义一个成员变量,都要设置其相应的setter和getter方法。
3.Xcode高级功能自动实现setter和getter:
①自动生成get方法和set方法:
@property int age;
其实编译器是很“笨”的,你怎么写他就怎么生成。写如上代码,编译器看到后,就自动变成
- (void)setAge:(int)age;
- (int)age;
相应的,它也完成了setter和getter方法的实现。
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
Xcode遵循一点,“没有我就生成,有我就用你的”。当什么都不定义就一句@property int age时,其实完成了三件事
- 定义了一个_age的成员变量。
- 声明了这个成员变量的getter和setter。
- 实现了这个成员变量的getter和setter。
②@synthesize是用于生成getter和setter的实现的。用在@implementation和@end之间。
@implementation Person
@synthesize age = _age;
@end
如果只写@synthesize age;就默认访问age而不是_age;如果此时没有写成员变量,就生成成员变量age。
③注意:
Xcode帮我们能够生成_age的原因是它要在get和set中访问调用。如果只写了set和get方法中的一个,另一个自动生
成。则Xcode依旧自动生成_age。但是如果set和get方法都是自己写的,那就不会再生成了。
在OC编程学习中,用的最多的还是@property。它可以生成下划线成员变量,getter,setter方法的声明和实现。并且遵
循我们习惯的书写规范(成员变量下划线开头)。剩下的仅作为了解。用了Xcode高级功能封装数据,可以节约出很多
写垃圾代码的时间,把更多的时间集合在思想上。
4.如果一个成员变量只允许访问不允许修改,那么这个成员变量就是只读的。这时候我们只提供它的get方法不提供set
方法就可以了。
5.OC的弱语法性:
①如果调用一个不存在的方法,编译可以通过,链接也可以通过,但是不能运行成功,会报一个经典的错误:unrecogined selector sent to intance。意思是给某个对象发送了一条不可识别的消息(方法)。这是一个编程中很
经常遇到的错误。
[1 2] --->2去1里找方法,找不到就报错。
②如果只写了方法声明,没有写实现,编译链接是可以通过的。OC是在运行工程中才会检测对象有没有实现相应的方
法。这时候会出现崩溃或者闪退现象。
③如果只写实现,不写声明。程序是可以运行成功的,但是不推荐。
④OC的本质还是面向过程的。
6.类方法:
①之前我们学习过以-开头的方法。这些方法都是由对象调用的,叫做对象方法。以+开头的是类方法。顾名思义,类方
法由类来调用。类方法无需创建对象。不依赖于对象就能实现方法,所以某种程度上提高了性能。例如我要设计计算器
的些许功能,求和求平方等等,这时候不需要成员变量的参与。这些方法都是类方法。
②类方法里只有方法,没有成员变量。所以类方法是决不能访问成员变量的。并且类方法和对象方法允许同名。
③类方法里自己调用自己,顾名思义,会产生死循环。
7.关键字self:
self是一个指针,指向调用当前方法的对象。说白了,就是当前对象/当前类。熟悉运用self,会感觉OC写起来“很方便”
- 使用 "self->成员变量名"访问当前方法调用的成员变量
- 使用 "[self方法名];"来调用方法(对象方法\类方法)
(二)继承:
继承其实并不陌生。@interface Car :NSObject 我们每次在创建类时候都要写一个:NSObject。这就是一个继承。
NSObject是Car的父类,也叫做超类。如果A继承B,那么A就拥有了B的所有属性,包括成员变量和所有方法。
@interfacePerson : NSObject
1.继承的好处和坏处:
①抽取重复代码。
②建立了类之间的关系。
③耦合性太强,两个类关系太密切。某个类不见了,另一个也就不能用了。所以说不是什么都可以随便继承。
2.之前我们通过new这个方法来实现类对对象的创建。其实new就是NSObjet的一个+类方法,通过继承,子类可以通过
new方法获得创造对象的能力。
3.能否继承,可以套用一句话,A 是 B。例如学生是人,那么学生类就可以拥有人这个类的所有属性。如果不适用,那
一般都不能继承。
4.因为子类继承父类,所以继承关系的类之间不允许拥有相同的成员变量,这样会产生重复定义的错误。
5.一个方法:重写-->子类重新实现父类的某个方法,覆盖父类以前的做法。调用某个对象方法时,优先是在当前对象中
找方法。当前对象中没有才去父类中寻找。下面由代码完成重写:
①首先定义Person类
#import <Foundation/Foundation.h>
@interface Person :NSObject
- (void) test;
@property int age;
@end
#import "Person.h"
@implementation Person
- (void) test
{
NSLog(@"我是Person父类");
}
@end
②定义Student类继承Person类
#import "Person.h"
@interface Student :Person
@end
#import "Student.h"
@implementation Student
- (void) test
{
NSLog(@"我是sTUDENT子类");
}
@end
由上代码。Student重写了Person的test函数。我们调用Student的test方法完成程序的执行。
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main()
{
Student *s = [Student new];
[stest];
return 0;
}
2015-04-02 16:18:58.507 oo[734:136700]我是sTUDENT子类
若要是不重写test方法,则现在当前类Student中找test方法,没有后去父类Person中找,找到后完成程序的执行。
执行结果:
2015-04-02 16:18:58.507 oo[734:136700]我是sTUDENT子类
6.继承和组合:
- 当两个类拥有相同的属性和方法时候,就可以把他们相同的东西抽到一个父类中。
- 当A类完全拥有B的属性时,例如人完全拥有学生的属性,那么学生就继承人
- 总的来说,子类的东西都要比父类多。因为可以再继承父类的基础上自己增加新的成员变量。
- 但不是一可以继承就是用继承,还有一种方法叫做组合。当A拥有B时,就是组合-->学生拥有成绩,他们的关系应该是组合。
组合指的是两个类不继承,但是一个类中得成员变量是另一个类。如下代码:
创建Student类继承Person,但是组合Score类
#import "Person.h"
#import "Score.h"
@interface Student : Person
{
NSString *_name;
Score *_score;
}
@end
Score类的声明:
#import <Foundation/Foundation.h>
@interface Score : NSObject
{
int _cScore;
int _ocScore;
}
@property int cScore;
@property int ocScore;
@end
这样,Student类就拥有了Score成绩类的属性。到时候只需创建成绩对象,把成绩对象通过setScore的方法赋值给
Student的成绩成员变量就可以了。
7.继承关键字super
super是父类的意思。用来调用父类的对象方法或类方法。当子类重写父类时,若想要保留父类的行为,往往用super。
这时候我们再次重写一下上面的Student类中得test方法,代码如下:
#import "Student.h"
@implementation Student
- (void) test
{
[super test];
NSLog(@"我是sTUDENT子类");
}
@end
程序输出结果为:
2015-04-02 16:35:58.970 oo[770:148770]我是Person父类
2015-04-02 16:35:58.971 oo[770:148770]我是sTUDENT子类
由此可见super的使用方法。
(三)多态:
多态是多种形态的意思。指的是父类指针指向子类对象的行为。例如上述的Student类继承Person类。
1.多态的定义实现如下:
Person *p = [Student new];
NSObject *n = [Person new];
NSObject *n1 = [Student new];
代码执行后,会动态检测指针的真实类型。所以其实p还是学生类,n是人类型,n1是学生类型。
2.多态的好处:
使用多态后,函数里可以写入方法。当有猫,狗,鸟等等动物类时,若要想用一个函数实现吃这个行为。只需传入一个
他们共同的父类Animal动物类,这样所有类都可以使用这个方法了。
void feed(Animal *a)
{
[a eat];
}
3.多态的坏处:
不可以使用父类指针调用子类方法。会警告。编译器会认为这个指针是Anmial类型,是一个父类类型。从而去父类中寻
找方法。但是方法是在子类中的。这种方法不推荐。
4.多态总结
:
- 无继承无多态。
- 代码体现:父类指针指向子类对象。
- 好处:函数/方法参数可以使用父类类型。
- 坏处:父类指针不可调用子类方法,除非强转。
- 黑马程序员_OC面向对象的三大特性
- 黑马程序员_oc面向对象三大特性
- 黑马程序员_OC语言之面向对象的三大特性(封装、继承、多态)
- 黑马程序员_OC面向对象的特性
- 黑马程序员_OC面向对象的三大特性之封装及OC中类方法和self的使用
- 黑马程序员_OC基础04_面向对象三大特性
- 黑马程序员_OC语言的面向对象特性
- 黑马程序员---面向对象三大特性
- 黑马程序员—面向对象的三大特性
- 黑马程序员_面向对象的三大特性
- "黑马程序员"面向对象的三大特性
- 黑马程序员 面向对象编程的三大特性
- 黑马程序员--------OC面向对象的三大特性
- 黑马程序员——面向对象的三大特性
- 黑马程序员之面向对象的三大特性(JAVA)
- 黑马程序员_面向对象三大特性
- 黑马程序员-java面向对象三大特性
- 黑马程序员----------面向对象三大特性之继承
- 设计模式实例-策略模式
- jquery中#的意思
- DNS解析与负载均衡
- [算法第一轮复习] 最短路算法之dijkstra
- 回朔法与动态规划的思考
- 黑马程序员_OC面向对象的三大特性
- 生活杂谈(一)
- poj1087 最大流
- 设计模式实例-抽象工厂模式
- Netty系列之Netty高性能之道
- AppCompat v7 No resource found that matches the given 错误
- Java 序列化的高级认识
- AspNet MVC4 教学-6:AspNet MVC4 CheckBox控件测试演示
- MVC上传文件后台获取不到值