封装,继承
- 封装:就是把抽象出的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。
- 封装实现三步骤
- 将属性进行私有化private【不能直接修改属性】
- 提供一个公共set方法,用于对属性判断并赋值。
- 提供一个公共的get方法,用于获取属性的值。
- 案例
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;} }
-
继承:解决代码复用性
-
继承可以解决代码复用,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可
-
语法:class 子类 extends 父类{ }
-
子类就会自动拥有父类定义的属性和方法
-
-
继承细节
-
子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
-
在用子类new个对象时,new Person():子类无参构造器被调用,必须调用父类的构造器,完成父类初始化(为什么父类构造器也被调用呢?):因为在子类默认无参构造器中的第一行语句有一个隐藏的命令,super();//默认调用父类的无参构造器,其实父类的无参构造器第一行也隐藏一个super。super是在构造器中的
-
当创建子类对象时,不管使用子类的那个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过。(super(12,"jiashuhang"))指定调用有参构造器
-
如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表)
-
super在使用时,必须放在构造器第一行(super只能在构造器中使用)
-
super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器。
-
java所有类都是Object类的子类,Object是所有类的基类
-
父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
-
子类最多只能继承一个父类(指直接继承),即java中是单继承机制。(思考如何放A类继承B类和C类):A继承B,B在继承C,中转一下就可
-
不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。(Person is a Music?)集成之间要有因果关心,(Dog is a animal)。
-
- 继承的本质
- 内存中发生了什么
-
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; // } }
- 内存中发生了什么