封装、继承、多态。

一、封装

1.为什么需要封装?

根据以前学的内容,假如我声明一个student类,里面有public成员age.。我在主函数中写代码 student *s = [studentnew]。这样的话我可以通过s→age修改age的值,但是会出现s→age=-10这种赋值,但是我们都知道年龄不可能为-10岁,我们没有办法阻值这种不合理的赋值。我们改变访问成员变量的方法,使得该方法能够滤掉不合理的赋值。

黑马程序员机器学习ppt 黑马程序员课程_子类

@interface就好像暴露在外面的时钟表面,像外界提供展示以及接口。@implementation就好像隐藏在时钟内部的构造实现,把具体的实现封装了起来。

2.Set方法:

在开发过程中,考虑到安全性要求,我们一般不在成员变量名前面使用@public、@protected等关键字修饰,而是使用Set方法来为对象提供成员变量的值。在set方法的内部也可以对一些不合理的赋值进行筛选过滤。

Set方法的作用:为外界提供一个设置成员变量值的方法

命名规范:

(1)方法名必须以set开头

(2)Set后面跟上成员变量的名称,首字母大写

(3)返回值一定是void

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

(5)形参名不能喝成员变量名一样(苹果官方推荐成员变量名前加_以示区分)

Set方法的好处:

(1)不让数据暴露在外,保证了数据的安全性

(2)对设置的数据进行过滤

Set方法使用示例:

Set方法的声明:

黑马程序员机器学习ppt 黑马程序员课程_子类_02

Set方法的实现:

黑马程序员机器学习ppt 黑马程序员课程_黑马程序员机器学习ppt_03

主函数:

黑马程序员机器学习ppt 黑马程序员课程_成员变量_04

3.get方法:

Get方法的作用:为调用者返回对象内部的成员变量

命名规范:

(1)一定有返回值,返回值的类型和成员变量的类型一致

(2)方法名和成员变量名一样

(3)不需要接收任何参数

Get方法使用示例:

Get方法的声明:

黑马程序员机器学习ppt 黑马程序员课程_成员变量_05

Get方法的实现:

黑马程序员机器学习ppt 黑马程序员课程_父类_06

主函数:

黑马程序员机器学习ppt 黑马程序员课程_成员变量_07

注意1:在实际的开发中,不一定set和get方法都会提供,如果内部的成员变量比如学生的学号这样的数据只允许外界读取,但是不允许修改的情况,则通常只提供get方法而不提供set方法。

注意2:成员变量名的命名以下划线开头,get方法名不需要带下划线,使用下划线开头有两个好处:(1)与get方法的方法名区分开来;(2)可以喝一些其他的局部变量区分开来,下划线开头的变量,通常都是类的成员变量。

4. 封装的好处:

把细节、内部成员隐藏在里面,保证了数据的安全性。有时候不会提供set方法和get方法,例如成员变量中如果有只读成员变量,只需提供get方法,不提供set方法即可。

6. 成员变量的命名规范:一定要以下划线_开头。好处为:

1>    观察4中实例里发现get的方法名和成员变量名一致,容易混淆。加入下划线可以区分这两个。

2>    可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量,方便交流。

 

二、继承

1.为什么要使用继承?

假如有一个类dog和一个类cat,他们的成员变量都是age、weight。方法也都一样。那么在两个类里面分别定义声明就很啰嗦,很多东西都是一样的。我们可以把这些相同的东西提取出来组成一个类animal,然后使用继承功能,使dog、cat继承animal类就具备animal的全部内容。在这个例子中dog、cat是animal的子类,animal是cat、dog的父类。使用这个功能可简化大量代码。

2.继承的好处:

1>抽取重复代码

2>建立了类的关系

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

3.注意点:基本上所有类的根类都是NSObject,new来自它,new是类方法。

4.继承使用注意点:

1>父类必须放在子类前面

2>不允许子类和父类拥有拥有相同名称的的成员变量

3>调用某个方法时,优先去当前类中找,如果找不到去父类找

5.重写:子类重新实现父类中的某个方法,称为重写,可以覆盖父类以前的做法。

6.继承的坏处:使代码的耦合性太强了

7.组合和继承区别:继承为xx是xx(student是person)、组合为xx有xx(student 有score)。

8.关键字super:

1>同self一样是不需要加@的关键字

2>直接调用父类中的某个方法

3>super处在对象方法中,那么就会调用父类对象方法;super处在类方法中,那么就会调用父类的类方法。

3>比较常见的使用场景为,子类重写父类方法时想保留父类的行为。

 

三、多态

1. 多态实质:父类指针指向子类对象,没有继承就没有多态

2.多态的好处

在2的基础上再设计一个类cat继承animal,重写eat方法,输出“cat eat----”,再设计一个函数feed函数如下:

void feed (dog*d)

{

        [d eat];

}

这个函数可以执行dog吃的动作,但是不能执行cat吃东西的动作,如果想在主函数中调用让cat吃东西的话,还要设计一个函数如下:

void feed2 (cat*c)

{

        [c eat];

}

这样在主函数中写入如下代码:

Dog *dd = [Dognew];

Cat *cc = [Catnew];

feed(dd);

feed(cc);

这样才能成功调用猫和狗的吃。

3.多态局限性:

如果上述例子的狗类中多加一个对象方法run,执行如下代码:

Animal *a = [Dognew];

[a run];

执行上述代码时发现有警告但能运行,我们规定不能这样写。这是多态的局限性:父类类型的指针不能用来调用子类的特有方法。如果实在想调用可以用强制转换的方法实现,代码如下:

Animal *a = [Dognew];

Dog *d = [Dog *]a;

[d run];

即必须转化为子类类型指针变量。