​活动地址:CSDN21天学习挑战赛

封装

一、封装的概念

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互.

二、封装的好处

1、隐藏细节,方便用户操作

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

三、如何封装?

1、私有化属性

2、提供一个公共方法set,用于对属性的值进行修改

3、提供一个公共方法get,用于获取属性的值。

4、将构造器中的赋值改成调用set方法。(选)

属性是私有的,在其他类中不能直接进行使用,只能通过set方法进行更改,通过get方法进行调用

四、封装实例

继承

一、继承的概念

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

二、继承示意图

三、继承的基本语法

class 子类名 extends 父类名{

}

1、子类继承了父类的所有的方法和属性,但私有的方法和属性不能再子类中直接访问。要通过公共方法访问。(在父类将私有的方法和属性封装)

package fabandsub;

public class Base {
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;
    public void Base(){
        System.out.println("base0.…");
    }
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400() {
        System.out.println("test400");
    }
    public void test500(){//封装test400方法
        test400();
    }

}

public class Sub extends Base { //子类I
    public Sub() {
        System.out.println("sub().……");
    }

    public void sayOk() {
        //我们发现父类的非private属性和方法
        // 都可以访问
        System.out.println(n1 +" "+ n2 +" "+ n3);
        Base();
        test100();
        test200();
        test300();
        test500();//可以通过这种方式曲线访问

    }
}

2、Object是所有类的父类,反之java的所有类都是object的子类

注:idea中ctel + h 可以提看类的继承关系

3、子类的构造器必须调用父类的构造器。

例如系统默认的无参构造器,在子类调用构造器时,会调用父类的无参构造器。

而如果父类的构造器是自定义的有参构造器,那必须在子类中调用父类的构造器。且必须在第一行调用

super(形参列表);   调用父类构造器,并输入参数

4、this和super不能共存。因为二者都要求放在第一行。

5、super会上溯至object(类的所有父类)

6、java是单继承机制,子类只能继承一个父类(直接继承)

7、不能滥用继承关系,一般认为:继承的父子必须直接满足:子类 is  a  父类。

 四、继承的本质

1、子类和父类间是一种索引关系,即对于子类来说,他有一个隐藏的属性为“父类”,继承事实上是对这一隐藏属性的赋值。加载时会先加载该属性,并先为该属性分配内存空间。

2、对象的创建:对象创建后,会为对象提供多个对象的栈,(同名的属性因为在不同的栈中还是会被创建完成)

2、同名属性的继承情况:

在访问一个属性时,会先访问当前类(子类),如果查找到就会返回,如果查找到的是私有的(不能使用)会返回并报错,如果没有则向上,查找父类;直到abject类。

package aandb;

class A{
    String name;
    A(){//A类中的A构造方法,同时输出”a“
        System.out.println("a");
    }
    A(String name) {//A类中的A构造方法(有参),同时输出a name
        System.out.println("a name");
    }
}
class B extends A{
    System name;
    B(){  //B类中的无参构造器,同时输出b
        this("abc"); 
        //由于this,所以没有super。同时this还会调用B的所有构造器
        System.out.println("b");
    }
    B(String name){
        System.out.println("b name");
    }
}

/
class xiaoyi {
    public static void main(String[] args){
        B b = new B();
    }
}

执行分析如下:
 * 当调用B的构造器时,实参列表内无参数,所以调用无参构造器
 * 进入无参构造器B,执行this指令,
 * this指令有参数,this指令顶掉super指令的同时,会调用相应的有参构造器,
 * 进入有参构造器内,会先执行默认的super,调用父类A的无参构造器A,
 * 无参构造器A会初输出“a",然后返回
 * 返回后输出“b name”,并返回
 * 返回后输出”b“,并返回,回到主函数
 * 主函数结束。

练习:

编写Computer类:

包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息

编写PC子类,继承Computer类,

添加特有属性【品牌brand】

编写NotePad子类,继承Computer类,添加特有属性【color】

编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法并打印输出信息。

五、super

1、可以访问父类的属性(非私有)

super。属性名   

什么意思呢?是否记得我们前边写的:2、对象的创建:对象创建后,会为对象提供多个对象的栈,(同名的属性因为在不同的栈中还是会被创建完成)因为我们不知道未来我们要命名的对象的名字是什么,所以采用super,代表“XXX的父类”. 属性,就像this代表当前类一样。

2、可以访问父类的方法(非私有):方法同上

3、访问父类的构造器(这点前边已经用过了):只能放在第一句,也只能用一句

super(形参列表);

4、为什么要有spuer呢?

super是java封装的代表,对于子类来说,父类的属性和方法只能用,不能修改,即使在实例化为对象以后也不能。一方面编程时增加了一定的工作量,另一方面整体上的规范化反而减少了工作量。

同时,当父子类中出现了同名属性或方法,可以通过super的方式来访问。父类的属性和方法,不需要改动父类的存储结构。

如果不出现重复名,那么无论哪个都一样。

有一个疑问:super如何向上跳过父类中的重名属性,访问爷爷的重名属性?

 

总结:无论是封装,继承还是之后的多态,本质上都是java增加代码复用性的办法。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐