面向对象特征之一:封装与隐藏

为什么需要封装?封装的作用和含义?
普通说明:

  • 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内 部的结构吗?有必要碰电动机吗?
  • 我要开车,…

代码说明: :::tips 一、问题的引入:
当我们创建一个类的对象以后,我们可以通过”对象.属性”的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs())
同时,我们需要避免用户再使用”对象.属性”的方式对属性进行赋值。则需要将属性声明为私有的(private).
此时,针对于属性就体现了封装性。 ::: :::tips 二、封装性的体现:
我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值。
拓展:封装性的体现:① 如上 ② 不对外暴露的私有的方法 ③ 单例模式
::: :::tips 三、封装性的体现,需要权限修饰符来配合。
1.Java规定的4种权限(从小到大排列):private、缺省、protected 、public
2.四种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
修饰类的话,只能使用:缺省、public

总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。 ::: image.png
image.png

  1. public class AnimalTest {
  2. public static void main(String[] args) {
  3. Animal a = new Animal();
  4. a.name = "大黄";
  5. // a.age = 1;
  6. // a.legs = 4;//The field Animal.legs is not visible
  7. a.show();
  8. // a.legs = -4;
  9. // a.setLegs(6);
  10. a.setLegs(-6);
  11. // a.legs = -4;//The field Animal.legs is not visible
  12. a.show();
  13. System.out.println(a.name);
  14. }
  15. }
  16. class Animal{
  17. String name;
  18. private int age;
  19. private int legs;//腿的个数
  20. //对属性的设置
  21. public void setLegs(int l){
  22. if(l >= 0 && l % 2 == 0){
  23. legs = l;
  24. }else{
  25. legs = 0;
  26. // 抛出一个异常(暂时没有讲)
  27. }
  28. }
  29. //对属性的获取
  30. public int getLegs(){
  31. return legs;
  32. }
  33. public void eat(){
  34. System.out.println("动物进食");
  35. }
  36. public void show(){
  37. System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
  38. }
  39. //提供关于属性age的get和set方法
  40. public int getAge(){
  41. return age;
  42. }
  43. public void setAge(int a){
  44. age = a;
  45. }
  46. }
  47. //private class Dog{
  48. //
  49. //}

面向对象特征之二:继承性(inheritance)

为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可。
:::tips 一、继承性的好处:
① 减少了代码的冗余,提高了代码的复用性
② 便于功能的扩展
③ 为之后多态性的使用,提供了前提 ::: :::tips 二、继承性的格式:
class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass ::: :::tips

  • 1.体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。

特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。
只有因为封装性的影响,使得子类不能直接调用父类的结构而已。

  • 2.子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。

    1. 子类和父类的关系,不同于子集和集合的关系。<br /> * extends:延展、扩展

    ::: :::tips 三、Java中关于继承性的规定:
    1.一个类可以被多个子类继承。
    2.Java中类的单继承性:一个类只能有一个父类
    3.子父类是相对的概念。
    4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
    5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法 ::: :::tips *四、 1. 如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
    2. 所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类
    3. 意味着,所有的java类具有java.lang.Object类声明的功能。 :::


面向对象特征之三:多态性

:::tips 1.理解多态性:可以理解为一个事物的多种形态。 ::: :::tips 2.何为多态性:对象的多态性
父类的引用指向子类的对象(或子类的对象赋给父类的引用)【我的理解:Person p1 = new Man();Man是Person的子类。】 ::: :::tips 3. 多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。 :::

//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 —-虚拟方法调用

:::tips 总结:编译,看左边;运行,看右边。 ::: :::tips 4.多态性的使用前提: ① 类的继承关系 ② 方法的重写 ::: :::tips 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边) ::: image.png :::success 1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中:编译看左边,运行看右边
2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量:编译运行都看左边 ::: :::info 如何才能调用子类特有的属性和方法?向下转型:使用强制类型转换符。
/使用强转时,可能出现ClassCastException的异常。
/
instanceof关键字的使用

a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。


使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先
进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。

如果 a instanceof A返回true,则 a instanceof B也返回true.
其中,类B是类A的父类。
/ :::