您的位置:首页 > 编程语言 > C语言/C++

黑马程序员—OC语言面向对象三大特性

2015-10-04 16:15 405 查看
学过面向对象语言的都知道,面向对象的三大特性是:继承、封装和多态。Objective-C作为一门面向对象语言当然也不例外,下面我将我最近学习中的关于三大特性的知识点和自己的理解做以下整理和总结,方便自己的学习和查阅!

一、封装

封装作为面向对象的三大特征之一,它指的是将对象的状态信息隐藏在对象内部,不允许外部外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。对一个类或者对象实现良好的封装,可以实现以下目的:

1、隐藏类的实现细节

2、让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里面加入控制逻辑,限制对成员变量的不合理访问。

3、可以进行数据检查,从而有利于保证对象信息的完整性。

4、便于修改,提高代码的可维护性。

为了实现代码的良好封装,需要从以下两个方面考虑:

1、 将对象的成员变量和实现细节隐藏起来,不允许外部直接访问。

2、把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。

因此,封装实际上有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。这两个方面都需要通过使用OC提供的访问控制符来实现。

Objective-C提供了4个访问控制符:@private @package @protected @public分别代表了4个访问控制级别。

1、@private :当前类访问权限(只能在当前类中访问)

2、@package :与当前访问权限相同

3、@protected :子类访问权限

4、@public :公共访问权限

封装的实现:

主要是依赖于setter方法和getter方法来实现的

1、setter方法

作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤

2、setter方法的命名规范:

1)方法名必须以set开头

2)set后面跟上成员变量的名称,成员变量的首字母必须大写

3)返回值一定是void

4)一定要接收一个参数,而且参数类型跟成员变量类型一致

5)形参的名称不能跟成员变量名一样

3、getter方法

作用:返回对象内部的成员变量

4、getter方法的命名规范:

1)肯定有返回值,返回值类型肯定与成员变量类型一致

2)方法名跟成员变量名一样

3)不需要接收任何参数

5、代码示例:

/*
设计一个成绩类
* C语言成绩(可读可写)
* OC成绩(可读可写)
* 总分(只读)
* 平均分(只读)
*/
#import <Foundation/Foundation.h>

@interface Score : NSObject
{
int _cScore;    // C语言成绩
int _ocScore;   // OC语言成绩
int _totalScore;    // 总分
int _averageScore;  // 平均分
}

// C语言成绩的setter和getter方法的声明
- (void)setCScore:(int)cScore;
- (int)cScore;

// OC语言成绩的setter和getter方法的声明
- (void)setOcScore:(int)ocScore;
- (int)ocScore;

- (int)totalScore;
- (double)averageScore;

@end

@implementation Score

// C语言成绩的setter和getter方法的实现
- (void)setCScore:(int)cScore
{
_cScore = cScore;

// 计算总分
_totalScore = _cScore + _ocScore;

_averageScore = _totalScore/2;
}
- (int)cScore
{
return _cScore;
}

// OC语言成绩的setter和getter方法的声明
- (void)setOcScore:(int)ocScore
{
_ocScore = ocScore;

// 计算总分
_totalScore = _cScore + _ocScore;

_averageScore = _totalScore/2;
}
- (int)ocScore
{
return _ocScore;
}

- (int)totalScore
{
return _totalScore;
}
- (double)averageScore
{
return _averageScore;
}

@end

int main()
{
Score *s = [Score new];
[s setCScore:100];
[s setOcScore:90];
int a = [s totalScore];
double b = [s averageScore];
NSLog(@"总分:%d,平均分:%f",a,b);
return 0;
}
二、继承

继承是面向对象的三大特征之一,也是实现软件复用的重要手段。Objective C的继承只有单继承的特点,每个子类只有一个直接父类。

1、当子类扩展父类时,子类可以继承得到父类的如下东西:

1) 全部成员变量

2)全部的方法

2、继承的好处:

1)抽取重复代码

2) 建立了类之间的关系

3)子类可以拥有父类的所有的成员变量和方法

3、注意点:

1)基本上所有类的根类是NSObject

4、继承的使用场合

1)当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中

2)当A类拥有B类中的部分属性和方法时,可以考虑让B类继承A类

如:

A
{
int _age;
int _no;
}

B
{
int _age;
int _no;
int _weight;
}
这时,A和B拥有共同的age和no成员变量,而B却又有自己新增的成员变量weight,这种情况就可以B继承于类A。

5、代码示例:

#import <Foundation/Foundation.h>

/*******Animal的声明********/
@interface Animal : NSObject
{
int _age;
double _weight;
}

- (void)setAge:(int)age;
- (int)age;

- (void)setWeight:(double)weight;
- (double)weight;

@end
/*******Animal的实现********/
@implementation Animal

- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}

- (void)setWeight:(double)weight
{
_weight = weight;
}
- (double)weight
{
return _weight;
}

@end
/*******Dog********/
// 继承Animal,相当于拥有了Animal里面的所有成员变量和方法
// Animal称为Dog的父类
// Dog称为Animal的子类
@interface Dog : Animal

@end

@implementation Dog

@end
/*******Cat********/
@interface Cat : Animal

@end

@implementation Cat

@end

int main()
{
Dog *d = [Dog new];

[d setAge:10];
NSLog(@"age=%d",[d age]);
return 0;
}
三、多态

Objective-C 指针类型的变量有两个:一个是编译时的类型,一个是运行时的类型,编译时的类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时不一致,就有可能出现所谓的多态。

1、没有继承就没有多态

2、代码的体现:父类类型的指针指向子类对象

3、好处:如果函数/方法参数中使用的是父类类型,可以传入父类、子类对象

4、局限性:

1)父类类型的变量不能直接调用子类特有的方法,必须强转为子类类型变量后,才能直接调用子类特有的方法

5、代码示例:

#import <Foundation/Foundation.h>

// 动物
@interface Animal : NSObject

- (void)eat;

@end

@implementation Animal

- (void)eat
{
NSLog(@"Animal-吃东西------");
}

@end

// 狗
@interface Dog : Animal
@end

@implementation Dog

- (void)eat
{
NSLog(@"Dog-吃东西--------");
}

@end

// 猫
@interface Cat : Animal

@end

@implementation Cat

- (void)eat
{
NSLog(@"Cat-吃东西-----");
}

@end

// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
[a eat];
}

int main()
{

Animal *aa = [Dog new];
// 多态的局限性:父类类型的变量  不能用来调用子类的方法
//[aa run];

// 将aa强制转换成Dog *类型的变量
Dog *dd = (Dog *)aa;
[dd run];

/*
Animal *aa = [Animal new];
feed(aa);

Dog *dd = [Dog new];
feed(dd);

Cat *cc = [Cat new];
feed(cc);
*/

//    // 多种形态
//    Dog *d = [Dog new];
//    // 父类指针指向子类对象
//    Animal *a = [Dog new];
//    [d eat];
//    [a eat];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: