Java-封装继承多态

目录

封装(encapsulation)

继承(extends)

super

多态(polymorphic)

多态细节


封装(encapsulation)

保护代码的私有性,项目的目的是给用户的,隐藏代码实现的一些细节,或者协保证代码的安全性。

  • 提高程序的安全性,保护数据

  • 隐藏代码的实现细节

  • 统一接口

  • 系统的可维护性增加

利用private修饰符进行封装(类的属性私有),如果在公共类中需要访问封装好的类时,在private的属性中通过get/set访问(Alt+Insert快捷键)(驼峰原则)同时可以根据一些规定在private的属性中进行一些修改,比如年龄必须是0-120之间,否则返回3等等规则。

在通过子类中的get方法(人为设置)访问私有数据

封装介绍

封装 ( encapsulation) 就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作

  • 封装的理解和好处

  1. 隐藏实现细节 方法(连接数据库)<----调用(传入参数...)

  2. 可以对数据进行验证,保证安全合理

    Person{name,age}

    Person p = new Person();

    p . name = "jack";

    p . age = 1200;//没有进行正确(合理)判断

  • 封装实现步骤(三步)

  1. 将属性进行私有化private【不能直接修改属性】

  2. 提供一个公用的(public)set方法,用于对属性判断并赋值

    public void setXxx(类型 参数名){//Xxx表示某个属性
        //加入数据验证的业务逻辑
        //属性 = 参数名;
    }
  3. 提供一个公用的(public)get方法,用于获取属性的值

    public void getXxx(){//权限判断,Xxx某个属性
        return xx;
    }

继承(extends)

通过extends关键字继承父类,Java中的类只有单继承。

继承的本质是对某一些类的抽象化,方便更好的管理代码。

继承是一种拓展,子类是父类的拓展(子类具有父类的一般特性)。

  • 继承是类和类的一种关系,除了继承,还有依赖,组合,聚合等

  • 继承关系的两个类,一个为子类(派生类)一个为父类(基础类)

  • 子类和父类之间有“is a”的关系

object是所有类的父类,使用时不需要继承(即系统会自动继承)(也叫做祖宗类)

  1. 子类继承了所有的属性和方法(只不过是private不显现,可以通过Debug工具看出),非私有的属性和方法可以在子类里直接访问,但是私有属性和方法不能在子类里直接访问,要通过父类提供公共的方法去访问

  2. 子类必须调用父类的构造器,完成父类的初始化

  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过

    使用方法:super(数据类型 变量名...);如果父类有多个构造器,一般只能用 super单独指定父类中的一个有参构造器,因为 super语句只能放在子类的第一句

  4. 如果需要指定去调用父类的某个构造器,则需要显式的调用一下:super(参数列表)

  5. super在使用时,需要且只能放在构造器的第一行

  6. super()和this()都只能放在构造器的第一行,且这两条语句不能同时存在于一个构造器当中

  7. Java所有类都是Object的子类,Object是所有类的基类

  8. 父类构造器的调用不限于直接父类!将一直向上追溯到Object类

  9. 子类最多只能继承一个父类(指直接继承),即Java中是单继承机制

  10. 不能滥用继承,子类和父类必须满足 is - a 的逻辑关系

继承的本质

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();//分析内存的布局
    }
}
class GrandPa{//父类的父类GrandPa
    String name = "强壮爷爷";
    String hobby = "钓鱼";
}
class Father extends GrandPa{//父类Father
    String name = "小头爸爸";
    int age = 39;
}
class Son extends Father{//子类Son
    String name = "大头儿子";
}

进行实例化Son()对象时,先加载顶级类Object的信息再加载GrandPa()信息,再加载Father()信息,最后加载Son信息


也就是再方法区中依次加载了四次信息

1.首先加载的爷爷类的属性会放在堆中的地址0X11中,属性指向方法区中常量池中的属性

2.然后加载父类的属性,但是如果父类的变量名和爷类的一致时,不会覆盖,会在堆中开辟另外的空间(基本数据类型只会存放在堆中,不会放在常量池中)然后再指向常量池中的变量

3.加载子类信息

4.栈中的main方法调用Son对象(地址)

按照查找关系来返回信息 1.首先看子类是否有该属性 2.如果子类有这个属性并且可以访问,则直接返回信息 3.如果子类没有这个属性,就一层一层依次向上查找该属性(并返回)

如果再查找过程中遇到有private的无法访问,则直接报错,不会再继续向上查找这个属性

如果要访问子类父类爷类中的同名属性,需要再父类爷类中设置返回需要的信息的方法

super

this关键字是指向当前类

super是指向父类

  • 父类中的private修饰的属性或者方法无法被子类调用,理论上来说是可以继承过去,但是无法被子类所访问(可以通过间接的方法访问)

子类和父类都有无参构造时

在调用子类的无参构造时,有一句隐藏的代码是super();(这句调用父类的构造器必须放在子类构造器内部的第一行)即默认先调用父类的无参构造


调用构造器时,只用调用父类或者子类的其中一个(调用子类需要把this放在第一行,调用父类需要把super放在第一行,如果同时调用,则会冲突)(子类继承父类后,父类有构造器的时候,子类会默认调用父类的构造器,也就是说这里如果只写this,这里的this也会报错(因为这里的this之前有默认调用父类的super))


当子类设置有参构造时,无参构造自动消除,即对父类的super无参构造无法使用

封装的时候,一个类无论怎么写,只要重写了有参构造,一般需要先把无参构造加上

如果没写父类的无参构造,子类仅可以调用父类的有参构造

多态(polymorphic)

方法重载(overloading)和方法覆盖(overriding)都是实现多态的手段,但是二者机制不同


抽象方法只起定义作用,不需要有方法体,一个类中如果全部都是抽象方法,基于称之为接口(interfere)只有接口的子类才可以实例化

  • 多[多种]态[状态]基本介绍

    方法或对象具有多种形态。是面对对象的第三大特征,多态时建立在封装和继承基础之上的

  • 多态具体体现

    1. 方法的多态 Ploy Demo 01 . java

      重写和重载体现多态

    2. 对象的多态(核心、困难、重点)

      • 一个对象的编译类型运行类型可以不一致

      • 编译类型在确定对象时,就确定了,不能改变

      • 运行类型时可以变化的

      • 编译类型看定义时 = 号的左边

        运行类型看定义时 = 号 的右

      案例:

      Animal animal = new Dog();[animal的编译类型是Animal,运行类型是Dog]

      animal = new Cat();[animal的运行类型变成了Cat,编译类型仍然是Animal]

    • 多态细节

      1. 多态的前提:两个对象(类)存在继承关系

      2. 多态的向上转型

        向上转型调用方法的规则如下

        1. 可以调用父类中的所有成员(需要遵守访问权限)

        2. 不能调用子类的特有的成员(因为在编译阶段,能调用那些成员都是由编译类型决定的)

        3. 最终运行效果看运行类型的具体实现,即调用方法时,按照运行类型开始查找方法,然后调用,规则与之前的访问规则一致

      3. 多态的向下转型

        • 语法子类类型 引用名 = (子类类型)父类引用

        • 只能强转父类的引用,不能强转父类的对象

        • 要求父类的引用必须指向的是当前目标类型的对象

        • 当向下转型后,才可以调用子类类型中的所有成员(也就是说父类不能直接调用子类的新方法)

      4. 属性没有重写之说!!!属性的值看编译类型

        (即属性不能动态绑定,在编译时就已经确定了)

        instanceof 比较操作符 用于判断对象的运行类型是否为XX类型或者XX类型的子类型

    • Java的动态绑定机制(very important a lot)

      动态绑定机制:

      1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

      2. 当调用对象属性时,没有动态绑定机制,那里声明就在那里使用

    • 多态的应用

      1. 多态数组

        数组的定义类型为父类类型,里面保存的实际元素为子类类型

        示例:

        Person[] persons = new Person[5];
        persons[0] = new Person("jack",20);//指向Person的数组数组某元素
        persons[1] = new Student("小王",18,100);//指向Student的数组某元素
        persons[2] = new Student("小明",19,65);
        persons[3] = new Teacher("李老师",29,8000);//指向Teacher的数组某元素
        persons[4] = new Teacher("赵老师",40,6000);
        ​
        //循环遍历多态数组
        for(int i = 0; i < persons.length; i++){
            System.out.println(persons[i].say());
            //
            if(persons[i] instanceof Student){//判断person[i]的运行类型是否是Student
                ((Student)persons[i]).study();//运行person数组中Student(子类)特有方法的语法
            //或者写成Student student = (Student) persons[i];
            //               student.study
            }else if(persons[i] instanceof Teacher){//保证进行类型转换时不会出错
                ((Teacher)persons[i]).teach();//执行Teacher中的特有方法teach()
            }else if (persons[i] instanceof Person){
        ​
            }else{
                System.out.println("类型有误,请自行检测");
            }

      2. 多态参数

        方法定义的形参类型为父类类型,实参类型允许为子类类型

你可能感兴趣的:(笔记,java)