> 文章列表 > 封装,继承

封装,继承

封装,继承

  1. 封装:就是把抽象出的数据【属性】和对数据的操作【方法封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。
  2. 封装实现三步骤
    1. 将属性进行私有化private【不能直接修改属性】
    2. 提供一个公共set方法,用于对属性判断并赋值。
    3. 提供一个公共的get方法,用于获取属性的值。
    4. 案例
      package com.hspedu.encap;//案例:不能随变查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证
      //年龄合理就设置,否则给默认年龄必须1-120之间
      //年龄工资不能直接查看,name的长度在2-6字符之间
      public class Encapsulation01 {public static void main(String[] args) {Person person = new Person();//person.setName("贾树行");person.name = "李四";//这个属性是公开的可以直接修改person.setAge(20);person.setSalary(30000);//构造器Person smith = new Person("smith", 2000, 30000);System.out.println("====smith的信息====");System.out.println(smith.info());System.out.println(person.info());//信息为:名字李四 age20 薪水30000.0}
      }class Person {public String name;//名字公开private int age;//私有化private double salary;//构造器 alt+insertpublic Person() {}public Person(String name, int age, double salary) {
      //这样的话之前的校验就被破解无用了
      //        this.name = name;
      //        this.age = age;
      //        this.salary = salary;
      //我们可以将set方法写在构造器中,这样仍然可以验证setName(name);//setAge(age);setSalary(salary);}public void setName(String name) {//加入对数据的校验if (name.length() >= 2 && name.length() <= 6) {this.name = name;} else {System.out.println("名字的长度不对需要(2-6)个字符,给了一个默认名字张三。");this.name = "张三";}}//自己写set,get太慢快捷键public String getName() {return name;}public int getAge() {return age;}public void setAge(int age) {if (age >= 1 && age <= 120) {this.age = age;} else {System.out.println("年龄需要在1-120之间,给默认年龄18");this.age = 18;//给一个默认年龄}}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public String info() {return "信息为:名字" + name + " age" + age + " 薪水" + salary;}
      }
      
  3. 继承:解决代码复用性

  4. 继承可以解决代码复用,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可

  5. 语法:class 子类 extends 父类{              }

    1. 子类就会自动拥有父类定义的属性和方法

  6. 继承细节

    1. 子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。

    2. 在用子类new个对象时,new Person():子类无参构造器被调用,必须调用父类的构造器,完成父类初始化(为什么父类构造器也被调用呢?):因为在子类默认无参构造器中的第一行语句有一个隐藏的命令,super();//默认调用父类的无参构造器,其实父类的无参构造器第一行也隐藏一个super。super是在构造器中的

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

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

    5. super在使用时,必须放在构造器第一行(super只能在构造器中使用)

    6. super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器。

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

    8. 父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)

    9. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制。(思考如何放A类继承B类和C类):A继承B,B在继承C,中转一下就可

    10. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。(Person is a Music?)集成之间要有因果关心,(Dog is a animal)。

  7. 继承的本质
    1. 内存中发生了什么
    2. package com.hspedu.extend_;public class ExtendsTheory {public static void main(String[] args) {Son son = new Son();//内存的布局//这时注意,要按照查找关系来返回信息//1.首先看子类是否有该属性//2.如果子类有这个属性,并且可以访问,则返回信息//3.如果子类没有这个属性,就看父类有没有这个属性,//(如果父类有该属性,并且可以访问,就返回信息)//4.如果父类没有就按照3.的规则,继续找上级,知道Object...System.out.println(son.name);//返回的就是大头儿子//System.out.println(son.getName());//返回的就是大头儿子System.out.println(son.age);//37System.out.println(son.hobby);//旅游}
      }
      class GrandPa{String name = "大头爷爷";String hobby = "旅游";
      }
      class Father extends GrandPa{String name = "大头爸爸";int age = 37;//private,如果把这个设置为私有的属性//那么通过son这个对象是访问不到age属性的//因为private只能在本类访问,new Father().
      }
      class Son extends Father{//子类String name = "大头 儿子";//私有的属性就用get方法访问ok//    public String getName() {
      //        return name;
      //    }
      }