面向对象之封装和多态

字数 1808阅读 27

封装(encapsulation)

为什么需要封装?封装的作用和含义?


我要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?

制造厂家为了方便我们使用电视,方便我们开车,把复杂的内部细节全部封装起来,只给我们暴露简单的接口,比如:电源开关、比如:油门。具体怎么内部实现的,我们不需要操心。

需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装。

白话:该露的露,该藏的藏

专业:我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

编程中封装的具体意义

便于调用者调用。

良好的封装,便于修改内部代码,提高可维护性。

良好的封装,可进行数据完整性检测,保证数据的有效性。

使用访问控制符,实现封装

范围越来越大


同一个类同一个包中子类所有类private*


default(即不加修饰符的时候)**

protected***
public****

封装的使用细节

属性一般使用 private (除非本属性确定会让子类继承并且使用)

提供相应的 get/set 方法来访问相关属性. 这些方法通常是 public,从而提供对属性的读取操作。(注意:boolean 变量的 get 方法是用:is 开头!)

一些只用于本类的辅助性方法可以用 private,希望其他类调用的方法用   public。
多态(polymorphism)

多态性是 OOP 中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。

多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法,从而实现更加灵活的编程,提高系统的可扩展性。

为什么需要多态?

多态性是指允许不同类的对象对同一消息作出不同的响应。

java 中如何实现多态 ? 使用多态的好处 ?

引用变量的两种类型:

  • 编译时类型(模糊一点,一般是一个父类)由声明时的类型决定。

  • 运行时类型(运行时,具体是哪个子类就是哪个子类)

  • 为什么会有这俩种类型呢
    在发生多态时,编译时看编译时类型,运行时看运行时类型。


    注:看代码里的注释,我结合代码分析了多态。


    编译可以理解为说,运行可以理解为做。比如你找了个女朋友,你对家长说像女明星,那到底是范冰冰还是杨幂还是刘宇春都不确定,当你带女朋友回家时,那这个女明星是谁就是谁。

    在上面这张图中,我们可以把圆,正方形,三角形抽象成为形状。那么形状会有 draw(画) 这个行为,当我们直接将 Circle 或 Square 或 Triangle 对象赋值给父类 Shape 的引用时,这个时候发生了多态。这样我们画一个形状就很灵活,只需要用父类 Shape 的引用 . draw(),那么具体是画什么样的形状就由赋值给父类引用的子类对象决定了。这样是不是就很灵活了呢?

    由实际对应的对象类型决定。通过动态绑定调用该对象的方法。动态绑定会使我们的程序编写更加灵活,但是会减慢程序运行速度。这也是 JAVA 比 C++/C 慢的主要原因之一。

    多态:如果编译时类型和运行时类型不一致,就会造成多态。(但是多态的存在要有3个必要条件的,下面会讲到

    方法绑定(method  binding)

    执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑定。

    静态绑定:

    在编译期完成,可以提高代码执行速度。

    动态绑定:

    通过对象调用的方法,采用动态绑定机制。 这虽然让我们编程灵活,但是降低了代码的执行速度。这也是 JAVA 比 C/C++ 速度慢的主要因素之一。 JAVA 中除了 final 类、final 方法、static 方法(因为这些是不可变的数据,在编译时期已经确认),其他所有方法都是 JVM 在运行期才进行动态绑定的。

    多态的使用要点

       1.    多态是方法的多态,属性没有多态性。

       2.    编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。但是如果两个没有关联的类进行强制转换,会报:ClassCastException。 比如:本来是狗,我把它转成猫。就会报这个异常。

       3.    多态的存在要有3个必要条件:要有继承,要有方法重写,父类引用指向子类对象引用。    4.     小口诀:编译看左边,运行看右边。

    对象的转型(casting)

    为什么需要强制转换类型?

    引用变量只能调用它编译类型的方法,不能调用它运行类型的方法。这时,我们就需要进行类型的强制转换!
    对应上面那个代码的例子:

    ((Circle) shape).area();


    一个父类的引用类型变量可以“指向”其子类的对象。


    一个父类的引用不可以访问其子类对象新增加的成员(属性和方法)。

    可以使用 引用 变量 instanceof 类名 来判断该引用型变量所“指向”的对象是否属于该类或该类的子类。

    子类的对象可以当作基类的对象来使用称作向上转型(upcasting),反之称为向下转型(downcasting)

    扫描下方二维码关注我们     

    现在的喜欢,其实不是真正的喜欢,只是因为不了解而已,真正的喜欢,是建立在非常了解的基础之上的。 

    了解 java 基础,喜欢上编程,不再迷茫。



    推荐阅读更多精彩内容