博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Objective-c》-(三大特性:封装、继承、多态)
阅读量:5972 次
发布时间:2019-06-19

本文共 5328 字,大约阅读时间需要 17 分钟。

 

一、封装(set方法和get方法)

  • 封装的好处:

 过滤掉不合理的值,屏蔽内部的赋值细节,让外界不比关心内部的细节。
  • set方法:

 1.作用:提供一个方法给外界设置成员变量的值

 2.命名规范:
   1> 方法名必须是set开头
   2> set后面跟上成员变量的名称,并且成员变量的首字母必须是大写
   3> 返回值一定是void
   4> 一定要接受一个参数,而且参数类型跟成员变量的类型一致
   5> 形参名称不能和成员变量名一样

 

例:

- (void)setAge : (int) newAge; // 方法声明- (void)setAge : (int) newAge // 方法实现{  if (newAge <= 0){  newAge = 1;  // 对传入的参数进行过滤 }  age = newAge;}
  •  get方法:

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

 2.命名规范:
   1> 肯定有返回值,并且返回值类型肯定和成员变量类型一致
   2> 方法名和成员变量名一样
   3> 不需要接受任何参数

例:

- (int) age; // 方法的声明- (int) age // 方法的实现{  return age;  }
  • 成员变量的命名规范

成员变量的命名规范:一定要以下划线“_”开头;

作用:1.让成员变量和get方法的名称区分开

         2.可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量

代码练习:

#import 
@interface Student : NSObject{ // 成员变量尽量不要用@public保证数据的安全性,没有@public就不能通过 对象->成员变量 来赋值(访问),这是可以提供一个set方法给外界设置成员变量的值(虽然没有了@public,但是在对象方法内还是能直接访问成员变量的) // @public int age;}- (void)setAge:(int)newAge;- (int)age;- (void)study;@end@implementation Student// set方法的实现- (void)setAge:(int)newAge{ // 对传进来的参数进行相应的过滤 if(newAge <= 0) { newAge = 1; } age = newAge;}// get方法的实现- (int)age{ return age;}- (void)study{ NSLog(@"%d岁的学生在学习", age); // 这里的使用age即使在声明成员变量时没有写@public也可以直接访问(对象方法内部可以直接访问成员变量)}@endint main(){ Student *stu = [Student new]; // 通过调用set方法对对象内部的成员变量进行赋值 [stu setAge:-10]; [stu study]; // 由于没有了@public这是调用get方法获取对象内部的成员变量值 NSLog(@"这个学生的年龄是%d", [stu age]); return 0;}

 

二、继承

1.继承的好处:

 

  • 抽取重复代码

  • 建立了类与类之间的关系

  • 子类拥有了父类中的所有成员变量和方法

2.继承的坏处:

  • 耦合性太强,子类与父类必须相互依存(如果将父类的代码 删除了,子类也不能正常使用);

3.继承注意点:

  • 基本所有类的根类是NSObject;

  • 父类的声明必须写在子类前面,实现无所谓;

  • 不允许子类有和父类相同的成员变量;

  • 调用某个方法时,优先在当前类中找,找不到就会去父类中找(内存分析见下图);

  • 允许子类中有和父类相同的方法,即:重写(子类重新实现父类中的某个方法,这是在子类中调用该方法就会优先执行子类中重新实现的方法,覆盖父类以前的方法)

 

 4.继承的使用场合:

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

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

  • 注意:1.并不是只要有相同的属性和方法就可以使用继承;

                2.使用继承时要考虑这两个类是否存在逻辑上的关系;

                3.如果不存在逻辑关系,就用组合

 代码一:

#import 
/*********Animal类的声明**********/@interface Animal : NSObject{ int _age; double _weight;}- (void)setAge:(int)age;- (int)age;@end/*********Animal类的实现**********/@implementation Animal- (void)setAge:(int)age{ _age = age;}- (int)age{ return _age;}@end// : Animal 代表Dog类继承了Animal类,那么Dog类中就拥有了Animal类中的所有成员变量及方法// Animal类就是Dog类的父类// Dog类就是Animal的子类/*********Dog类的声明**********/@interface Dog : Animal@end/*********Dog类的实现**********/@implementation Dog@endint main(){ Dog *d = [Dog new]; [d setAge:10]; NSLog(@"age=%d", [d age]); return 0;}

 代码二:

#import 
@interface Person : NSObject{ int _age;}- (void)run;@end@implementation Person- (void)run{ NSLog(@"person---跑");}@end// 注意点1:子类的声明必须写在父类的声明后面@interface Student :Person{ int _no;// 注意点2:不允许在子类中有和父类相同的成员变量 // int _age; // 报错:重复定义_age(error: duplicate member '_age')}// - (void)run; // 这里可以不写,因为在其父类中已经有声明,如果子类实现中有该方法的实现,就是重写(子类重新实现父类中的某个方法)@end@implementation Student// 重写:子类重新实现父类中的某个方法,这是在子类中调用该方法就会优先执行子类中重新实现的方法,覆盖父类以前的方法- (void)run{ NSLog(@"student---跑");}@endint main(){ Student *s = [Student new]; [s run]; // 会现在子类中找run方法,找到了就优先执行当前类中run方法,没有找到就会去其父类中找 return 0;}

 

代码三:

#import 
@interface Score : NSObject{ int _cScore; int _ocScore;}@end@implementation Score@end// 继承:xx 是 xxx// 组合:xx 拥有 xxx@interface Student :NSObject{ int _no; int _age; Score *_score; // 这里用的就是组合}@end@implementation Student@endint main(){ return 0;}

 

 三、多态(父类指针指向子类对象)

1.代码体现:父类类型的指针指向子类对象;

2.好处:如果函数、方法形参中使用的是父类类型,就可以传入父类、子类对象;

3.局限性:父类类型的变量不能直接调用子类特有的方法,必须强转为子类类型后才能直接调用子类特有方法

 

 

 4.代码练习:

#import 
@interface Animal : NSObject- (void)eat;@end@implementation Animal- (void)eat{ NSLog(@"Animal---吃东西");}@end@interface Dog : Animal- (void)run;@end@implementation Dog- (void)eat{ NSLog(@"Dog---吃东西");}- (void)run{ NSLog(@"狗跑起来了");}@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 feed3(Animal *a){ [a eat];}int main(){ /***************1.多态的基本使用******************/ // 多态:父类指针指向子类对象 Animal *a = [Dog new]; // 调用方法时会动态检测对象的真实类型,这里对象a的真实类型是Dog [a eat]; // 输出:Dog---吃东西 /***************2.OC的弱语法******************/ /* 注意点: OC的弱语法:这里仅仅是一个警告(warning: incompatible pointer types initializing 'Dog *' with an expression of type 'Animal *' [-Wincompatible-pointer-types]) */ // Dog *d = [Animal new]; // 虽然仅仅是一个警告,但是在意思上不合理(动物是狗) // [d eat]; // 输出:Animal---吃东西 /***************3.多态的好处******************/ // 多态的好处:如果形参中使用的是父类类型,就可以传入父类、子类对象 Dog *d2 = [Dog new]; feed(d2); Cat *c2 = [Cat new]; feed2(c2); Dog *d3 = [Dog new]; feed3(d3); Cat *c3 = [Cat new]; feed3(c3); /***************4.多态的局限性******************/ Dog *dd = [Dog new]; // Dog类型 Animal *aa = [Dog new]; // Animal类型 // OC的弱语法: warning: 'Animal' may not respond to 'run' // 对于编译器来讲,编译器认为aa的类型是Animal,这里[aa run]就会去Animal中找是否有run的具体实现,没有找到就会警告,但是 还是会运行成功,因为在运行是会动态检测aa的真实类型(Dog),Dog类中有run方法的具体实现,就能正常运行 // 多态的局限性:父类类型的变量不能用来调用子类特有的方法 // [aa run]; // 对于上面的问题,可以将aa强制转换成Dog类型,编译器就不会警告 Dog *dd = (Dog *)aa; // 将aa强制转换成Dog *类型 [dd run]; return 0;}

 

 
 
 
 
 

转载于:https://www.cnblogs.com/unique-ios/p/4322564.html

你可能感兴趣的文章
讲解sed用法入门帖子
查看>>
Java异常学习心得
查看>>
Scala学习之类和属性篇(一):定义类的主构造方法
查看>>
使用阿里云CentOS安装LAMP时,安装PHP扩展需要注意的事情
查看>>
Linux 内核已支持苹果
查看>>
shell脚本逻辑判断,文件目录属性判断,if,case用法
查看>>
【二叉树系列】二叉树课程大作业
查看>>
JAVA spring配置文件总结
查看>>
Java5的 线程并发库
查看>>
HDOJ 1036 输入输出 水
查看>>
Java 安装后的检测是否安装成功
查看>>
设备及分辨率
查看>>
mybatis拦截器
查看>>
App重新启动
查看>>
矩阵乘法
查看>>
得到目标元素距离视口的距离以及元素自身的宽度与高度(用于浮层位置的动态改变)...
查看>>
安装和配置Tomcat
查看>>
实验三
查看>>
第一次实验总结
查看>>
openssh for windows
查看>>