OC面向对象的三大特性
2014-12-12 13:43
176 查看
一、面向对象的三大特性:封装(成员变量)、继承和多态
1、 set方法和get方法
1. set方法和get方法的使用场合
@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数
2. set方法
1) 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值
2) 命名规范:
➢ 方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
➢ 形参名称不要跟成员变量同名
3. get方法
1) 作用:返回对象内部的成员变量
2) 命名规范:get方法的名称一般就跟成员变量同名
4. 成员变量的命名规范
➢ 成员变量都以下划线 _ 开头
➢ 可以跟get方法的名称区分开
➢ 可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量
5. 代码示例
#import <Foundation/Foundation.h>
// 声明
@interface Car : NSObject
{
int _wheels; // 轮子个数
}
/*set方法*/
- (void) setWheels:(int)wheels;
/*get方法*/
- (int) wheels;
@end
@implementation Car
// set方法的实现
- (void) setWheels:(int)wheels
{
// 对外面传进来的轮子数进行过滤
if (wheels<=0)
{
wheels = 1;
}
_wheels = wheels;
}
// get方法的实现
- (int) wheels
{
return _wheels;
}
@end
6. 封装的好处
➢ 过滤不合理的值
➢ 屏蔽内部的赋值过程
➢ 让外界不必关注内部的细节
2、 类方法
1. 基本概念
直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)
2. 类方法和对象方法对比
1) 对象方法
➢ 以减号-开头
➢ 只能让对象调用,没有对象,这个方法根本不可能被执行
➢ 对象方法能访问实例变量(成员变量)
2) 类方法
➢ 以加号+开头
➢ 只能用类名调用,对象不能调用
➢ 类方法中不能访问实例变量(成员变量)
➢ 使用场合:当不需要访问成员变量的时候,尽量用类方法
3) 类方法和对象方法可以同名
3、 self关键字
1. 成员变量和局部变量同名
➢ 当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
➢ 用self访问成员变量,区分同名的局部变量
2. 使用细节
1) 出现的地方:所有的OC方法中(对象方法\类方法),不能出现在函数
2) 作用
➢ 使用 "self->成员变量名" 访问当前方法调用的成员变量
➢ 使用 "[self 方法名];" 来调用方法(对象方法\类方法)
3. 常见错误
➢ 低级错误:用self去调用函数
➢ 类方法中用self调用对象方法,对象方法中用self调用类方法
➢ self死循环
练习:设计一个成绩类
* C语言成绩(可读可写)
* OC成绩(可读可写)
* 总分(只读)
* 平均分(只读)
二、 继承
1. 继承的基本用法
● 设计两个类Bird、Dog
// Bird的声明
@interface Bird : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Bird的定义
@implementation Bird
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
// Dog的声明
@interface Dog : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Dog的定义
@implementation Dog
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
● 有相同的属性和行为,抽出一个父类Animal(先抽取weight属性,再抽取eat方法)
// Animal的声明
@interface Animal : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Animal的定义
@implementation Animal
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
● 子类在父类的基础上拓充属性和方法
// Bird的声明
@interface Bird : Animal
{
@public
int height;
}
- (void)fly;
@end
// Bird的定义
@implementation Bird
- (void)fly {
NSLog(@"飞飞飞-高度:%d", height);
}
@end
// Dog的声明
@interface Dog : Animal
{
@public
int speed;
}
- (void)run;
@end
// Dog的定义
@implementation Dog
- (void)run {
NSLog(@"跑跑跑-高度:%d", speed);
}
@end
● 子类方法和属性的访问过程:如果子类没有,就去访问父类的
● 父类被继承了还是能照常使用的
● 父类的静态方法
● 画继承结构图,从子类抽取到父类
● NSObject的引出:全部OC类的最终父类,包含了一些常用方法,比如+new
2. 继承的专业术语
● 父类\超类 superclass
● 子类 subclass\subclasses
3. 继承的细节
● 单继承
● 子类和父类不能有相同的成员变量
● 方法的重写
4. super关键字
● 分别调用父类的对象方法和类方法
在子类中重写方法时,可以让调用者跳过这一层而调用父类中的方法。
5. 继承的好处
● 不改变原来模型的基础上,拓充方法
● 建立了类与类之间的联系
● 抽取了公共代码
● 坏处:耦合性强
6. 继承的使用场合
● 它的所有属性都是你想要的,一般就继承
● 它的部分属性是你想要的,可以抽取出另一个父类
继承的使用场合练习
1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中
2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类
A
{
int _age;
int _no;
}
B : A
{
int _weight;
}
// 继承:xx 是 xxx
// 组合:xxx 拥有 xxx
2.组合
A
{
int _age;
int _no;
}
B
{
A *_a;
int _weight;
}
三、多态
1. 多态的基本概念
● 某一类事物的多种形态,必须要有继承,没有继承就没有多态。
● OC对象具有多态性,多态在代码中的体现即父类指针指向子类对象。
2. 多态的体现
Person *p = [Student new];
p->age = 100;
[p walk];
● 子类对象赋值给父类指针
● 父类指针访问对应的属性和方法
3. 多态的好处
● 用父类接收参数,节省代码
4. 多态的局限性
● 不能访问子类的属性(可以考虑强制转换)
5. 多态的细节
● 动态绑定:在运行时根据对象的类型确定动态调用的方法
[b]多态使用总结[/b]
1.没有继承就没有多态
2.代码的体现:父类类型的指针指向子类对象
3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法
3、 NSString的简单使用
1. 字符串的快速创建
NSStirng *str = @“Hello”;
2. 使用静态方法创建
3. 使用%@输出字符串
NSString *name = @”mj”;
NSLog(@“我的名字是%@”, name);
作业
1、 set方法和get方法
1. set方法和get方法的使用场合
@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数
2. set方法
1) 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值
2) 命名规范:
➢ 方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
➢ 形参名称不要跟成员变量同名
3. get方法
1) 作用:返回对象内部的成员变量
2) 命名规范:get方法的名称一般就跟成员变量同名
4. 成员变量的命名规范
➢ 成员变量都以下划线 _ 开头
➢ 可以跟get方法的名称区分开
➢ 可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量
5. 代码示例
#import <Foundation/Foundation.h>
// 声明
@interface Car : NSObject
{
int _wheels; // 轮子个数
}
/*set方法*/
- (void) setWheels:(int)wheels;
/*get方法*/
- (int) wheels;
@end
@implementation Car
// set方法的实现
- (void) setWheels:(int)wheels
{
// 对外面传进来的轮子数进行过滤
if (wheels<=0)
{
wheels = 1;
}
_wheels = wheels;
}
// get方法的实现
- (int) wheels
{
return _wheels;
}
@end
6. 封装的好处
➢ 过滤不合理的值
➢ 屏蔽内部的赋值过程
➢ 让外界不必关注内部的细节
/** 4.设计Car类 1> 属性 * 速度 2> 方法 * 属性相应的set和get方法 * 一个对象方法跟其他车子比较车速,返回速度差 * 一个类方法比较两辆车的车速,返回速度差 */ #import <Foundation/Foundation.h> // 车 @interface Car : NSObject { int _speed; // 速度 } // 速度的getter和setter - (void)setSpeed:(int)speed; - (int)speed; // 跟其他车子比较车速,返回速度差 - (int)compareSpeedWithOther:(Car *)car; // 比较两辆车的车速,返回速度差 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2; @end @implementation Car // 速度的getter和setter - (void)setSpeed:(int)speed { _speed = speed; } - (int)speed { return _speed; } // 跟其他车子比较车速,返回速度差 - (int)compareSpeedWithOther:(Car *)car { // 第1种思路 // return _speed - [car speed]; // 第2种思路 return [Car compareSpeedBetweenCar1:self andCar2:car]; } // 比较两辆车的车速,返回速度差 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2 { return [car1 speed] - [car2 speed]; } @end
2、 类方法
1. 基本概念
直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)
2. 类方法和对象方法对比
1) 对象方法
➢ 以减号-开头
➢ 只能让对象调用,没有对象,这个方法根本不可能被执行
➢ 对象方法能访问实例变量(成员变量)
2) 类方法
➢ 以加号+开头
➢ 只能用类名调用,对象不能调用
➢ 类方法中不能访问实例变量(成员变量)
➢ 使用场合:当不需要访问成员变量的时候,尽量用类方法
3) 类方法和对象方法可以同名
3、 self关键字
1. 成员变量和局部变量同名
➢ 当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
➢ 用self访问成员变量,区分同名的局部变量
2. 使用细节
1) 出现的地方:所有的OC方法中(对象方法\类方法),不能出现在函数
2) 作用
➢ 使用 "self->成员变量名" 访问当前方法调用的成员变量
➢ 使用 "[self 方法名];" 来调用方法(对象方法\类方法)
3. 常见错误
➢ 低级错误:用self去调用函数
➢ 类方法中用self调用对象方法,对象方法中用self调用类方法
➢ self死循环
练习:设计一个成绩类
* C语言成绩(可读可写)
* OC成绩(可读可写)
* 总分(只读)
* 平均分(只读)
#import <Foundation/Foundation.h> @interface Score : NSObject { int _cScore; // C语言成绩 int _ocScore; // OC成绩 int _totalScore;// 总分 int _averageScoe; // 平均分 } - (void)setCScore:(int)cScore; - (int)cScore; - (void)setOcScore:(int)ocScore; - (int)ocScore; - (int)totalScore; - (int)averageScore; @end @implementation Score - (void)setCScore:(int)cScore { _cScore = cScore; // 计算总分 _totalScore = _cScore + _ocScore; _averageScoe = _totalScore/2; } - (int)cScore { return _cScore; } - (void)setOcScore:(int)ocScore { _ocScore = ocScore; // 计算总分 _totalScore = _cScore + _ocScore; _averageScoe = _totalScore/2; } // 监听成员变量的改变 - (int)ocScore { return _ocScore; } - (int)totalScore { return _totalScore; } - (int)averageScore { return _averageScoe; } @end int main() { Score *s = [Score new]; [s setCScore:90]; [s setOcScore:100]; [s setCScore:80]; int a = [s totalScore]; NSLog(@"总分:%d", a);
二、 继承
1. 继承的基本用法
● 设计两个类Bird、Dog
// Bird的声明
@interface Bird : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Bird的定义
@implementation Bird
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
// Dog的声明
@interface Dog : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Dog的定义
@implementation Dog
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
● 有相同的属性和行为,抽出一个父类Animal(先抽取weight属性,再抽取eat方法)
// Animal的声明
@interface Animal : NSObject
{
@public
int weight;
}
- (void)eat;
@end
// Animal的定义
@implementation Animal
- (void)eat {
NSLog(@"吃吃吃-体重:%d", weight);
}
@end
● 子类在父类的基础上拓充属性和方法
// Bird的声明
@interface Bird : Animal
{
@public
int height;
}
- (void)fly;
@end
// Bird的定义
@implementation Bird
- (void)fly {
NSLog(@"飞飞飞-高度:%d", height);
}
@end
// Dog的声明
@interface Dog : Animal
{
@public
int speed;
}
- (void)run;
@end
// Dog的定义
@implementation Dog
- (void)run {
NSLog(@"跑跑跑-高度:%d", speed);
}
@end
● 子类方法和属性的访问过程:如果子类没有,就去访问父类的
● 父类被继承了还是能照常使用的
● 父类的静态方法
● 画继承结构图,从子类抽取到父类
● NSObject的引出:全部OC类的最终父类,包含了一些常用方法,比如+new
2. 继承的专业术语
● 父类\超类 superclass
● 子类 subclass\subclasses
3. 继承的细节
● 单继承
● 子类和父类不能有相同的成员变量
● 方法的重写
4. super关键字
● 分别调用父类的对象方法和类方法
在子类中重写方法时,可以让调用者跳过这一层而调用父类中的方法。
/* 僵尸 跳跃僵尸、舞王僵尸、铁桶僵尸 */ #import <Foundation/Foundation.h> /* super的作用 1.直接调用父类中的某个方法 2.super处在对象方法中,那么就会调用父类的对象方法 super处在类方法中,那么就会调用父类的类方法 3.使用场合:子类重写父类的方法时想保留父类的一些行为 */ // 僵尸 @interface Zoombie : NSObject - (void)walk; + (void)test; - (void)test; @end @implementation Zoombie - (void)walk { NSLog(@"往前挪两步******"); } + (void)test { NSLog(@"Zoombie+test"); } - (void)test { NSLog(@"Zoombie-test"); } @end // 跳跃僵尸 @interface JumpZoombie : Zoombie + (void)haha; - (void)haha2; @end @implementation JumpZoombie + (void)haha { [super test]; } - (void)haha2 { [super test]; } - (void)walk { // 跳两下 NSLog(@"跳两下"); // 走两下(直接调用父类的walk方法) [super walk]; //NSLog(@"往前挪两步----"); } @end int main() { //[JumpZoombie haha]; JumpZoombie *jz = [JumpZoombie new]; [jz walk]; return 0; }
5. 继承的好处
● 不改变原来模型的基础上,拓充方法
● 建立了类与类之间的联系
● 抽取了公共代码
● 坏处:耦合性强
6. 继承的使用场合
● 它的所有属性都是你想要的,一般就继承
● 它的部分属性是你想要的,可以抽取出另一个父类
继承的使用场合练习
1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中
2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类
A
{
int _age;
int _no;
}
B : A
{
int _weight;
}
// 继承:xx 是 xxx
// 组合:xxx 拥有 xxx
2.组合
A
{
int _age;
int _no;
}
B
{
A *_a;
int _weight;
}
#import <Foundation/Foundation.h> /* 1.继承的好处: 1> 抽取重复代码 2> 建立了类之间的关系 3> 子类可以拥有父类中的所有成员变量和方法 2.注意点 1> 基本上所有类的根类是NSObject */ /********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里面的所有成员变量和方法 // 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; }
三、多态
1. 多态的基本概念
● 某一类事物的多种形态,必须要有继承,没有继承就没有多态。
● OC对象具有多态性,多态在代码中的体现即父类指针指向子类对象。
2. 多态的体现
Person *p = [Student new];
p->age = 100;
[p walk];
● 子类对象赋值给父类指针
● 父类指针访问对应的属性和方法
3. 多态的好处
● 用父类接收参数,节省代码
4. 多态的局限性
● 不能访问子类的属性(可以考虑强制转换)
5. 多态的细节
● 动态绑定:在运行时根据对象的类型确定动态调用的方法
[b]多态使用总结[/b]
1.没有继承就没有多态
2.代码的体现:父类类型的指针指向子类对象
3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法
#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() { // 多态的局限性:父类类型的变量 不能 用来调用子类的方法 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; }
3、 NSString的简单使用
1. 字符串的快速创建
NSStirng *str = @“Hello”;
2. 使用静态方法创建
3. 使用%@输出字符串
NSString *name = @”mj”;
NSLog(@“我的名字是%@”, name);
#import <Foundation/Foundation.h> @interface Person : NSObject { //char *_name; NSString *_name; } @end int main() { /* // 最简单的创建字符串的方式 NSString *str = @"itcast"; char *name = "itcast"; NSLog(@"我在%@上课", str); //NSLog(@"%s", name); */ int age = 15; int no = 5; NSString *name = @"哈哈jack"; // length方法算的是字数 int size = [name length]; NSLog(@"%d", size); // 创建OC字符串的另一种方式 NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name]; NSLog(@"---- %ld", [newStr length]); return 0; }
作业
/** 6.设计一个类Circle,用来表示二维平面中的圆 1> 属性 * double radius (半径) * Point2D *point (圆心) 2> 方法 * 属性相应的set和get方法 * 设计一个对象方法判断跟其他圆是否相交(重叠返回YES,否则返回NO) * 设计一个类方法判断两个圆是否相交(重叠返回YES,否则返回NO) */ #import <Foundation/Foundation.h> #import <math.h> // 点 @interface Point2D : NSObject { double _x; // x值 double _y; // y值 } // x值的getter和setter - (void)setX:(double)x; - (double)x; // y值的getter和setter - (void)setY:(double)y; - (double)y; // 同时设置x和y - (void)setX:(double)x andY:(double)y; // 计算跟其他点的距离 - (double)distanceWithOther:(Point2D *)other; // 计算两个点之间的距离 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2; @end @implementation Point2D // x值的getter和setter - (void)setX:(double)x { _x = x; } - (double)x { return _x; } // y值的getter和setter - (void)setY:(double)y { _y = y; } - (double)y { return _y; } // 同时设置x和y - (void)setX:(double)x andY:(double)y { // 第1种思路 // _x = x; // _y = y; // 第2种思路 [self setX:x]; [self setY:y]; } // 计算跟其他点的距离 - (double)distanceWithOther:(Point2D *)other { // 不要再傻乎乎算一遍了,直接调用类方法即可 return [Point2D distanceBetweenPoint1:self andPoint2:other]; } // 计算两个点之间的距离 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2 { // 两点距离公式:( (x1-x2)的平方 + (y1-y2)的平方 )开根 // x1-x2 double xDelta = [p1 x] - [p2 x]; // (x1-x2)的平方 double xDeltaPingFang = pow(xDelta, 2); // y1-y2 double yDelta = [p1 y] - [p2 y]; // (y1-y2)的平方 double yDeltaPingFang = pow(yDelta, 2); return sqrt(xDeltaPingFang + yDeltaPingFang); } @end // 圆 @interface Circle : NSObject { double _radius; // 半径 Point2D *_point; // 圆心 } // 半径的getter和setter - (void)setRadius:(double)radius; - (double)radius; // 圆心的getter和setter - (void)setPoint:(Point2D *)point; - (Point2D *)point; // 跟其他圆是否重叠(重叠返回YES,否则返回NO) - (BOOL)isInteractWithOther:(Circle *)other; // 判断两个圆是否重叠(重叠返回YES,否则返回NO) + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2; @end @implementation Circle // 半径的getter和setter - (void)setRadius:(double)radius { _radius = radius; } - (double)radius { return _radius; } // 圆心的getter和setter - (void)setPoint:(Point2D *)point { _point = point; } - (Point2D *)point { return _point; } // 跟其他圆是否重叠(重叠返回YES,否则返回NO) - (BOOL)isInteractWithOther:(Circle *)other { return [Circle isInteractBetweenCircle1:self andCircle2:other]; } // 判断两个圆是否重叠(重叠返回YES,否则返回NO) + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2 { // 如果两个圆心的距离 >= 两个圆的半径和,就不重叠 // 如果两个圆心的距离 < 两个圆的半径和,就重叠 // 两个圆心 Point2D *point1 = [circle1 point]; Point2D *point2 = [circle2 point]; // 两个圆心的距离 double distance = [point1 distanceWithOther:point2]; // 半径和 double radiusSum = [circle1 radius] + [circle2 radius]; return distance < radiusSum; } @end int main() { Circle *c1 = [Circle new]; // 设置半径 [c1 setRadius:2]; // 设置圆心 Point2D *p1 = [Point2D new]; [p1 setX:10 andY:10]; [c1 setPoint:p1]; Circle *c2 = [Circle new]; // 设置半径 [c2 setRadius:2]; // 设置圆心 Point2D *p2 = [Point2D new]; [p2 setX:13 andY:14]; [c2 setPoint:p2]; // 圆心距离是5 半径和是4 所以不重叠 BOOL b1 = [c1 isInteractWithOther:c2]; BOOL b2 = [Circle isInteractBetweenCircle1:c1 andCircle2:c2]; NSLog(@"%d %d", b1, b2); return 0; }
相关文章推荐
- oc语言--面向对象的三大特性
- 黑马程序员——OC基础---面向对象(思想,类,对象,三大特性)
- Objective C(OC)面向对象三大特性之:封装
- 黑马程序员_OC基础04_面向对象三大特性
- 黑马程序员---OC--面向对象三大特性
- 黑马程序员——OC语言基础——面向对象三大特性之继承
- 黑马程序员——【OC】面向对象的三大特性
- 黑马程序员——OC语言基础:面向对象三大特性,封装、继承、多态
- OC面向对象三大特性
- OC面向对象的三大特性:封装,继承,多态
- OC面向对象_三大特性
- 黑马程序员——OC语言基础——面向对象三大特性之多态
- 黑马程序员—OC语言面向对象三大特性
- OC温故:面向对象的三大特性(封装,继承,多态)
- 黑马程序员————OC面向对象_三大特性之封装
- 黑马程序员--------OC面向对象的三大特性
- 黑马程序员——OC面向对象三大特性——封装,继承,多态。
- OC中的面向对象三大特性之
- 黑马程序员————IOS学习笔记 第3篇 OC面向对象三大特性(1)
- 黑马程序员——OC—面向对象的三大特性