Java之封装、继承,多态

文章目录

  • Java 之封装、继承,多态
    • 一、封装
      • 1.封装的基本介绍
      • 2. 封装的实现
      • 3. 将构造器与 setXxx 方法结合
    • 二、继承
      • 1. 继承的基本介绍
      • 2. 基本语法
      • 3.继承的深入理解
      • 4. 继承的本质分析(内存存在形式)
      • 5. 子类创建的内存布局
      • 6. super 关键字
        • 6.1 super 的基本介绍
        • 6.2 基本语法
        • 6.3 使用时的注意事项
        • 6.4 super 带来的好处
        • 6.5 super 和 this 的比较
      • 7. 方法重写/覆盖(override)
        • 7.1 基本介绍
        • 7.2 使用方式、细节、注意事项
        • 7.3 方法重载和方法重写(覆盖)的比较
    • 三、多态
      • 1. 基本介绍
      • 2. 具体体现
        • 2.1 方法的多态
        • 2.2 对象的多态
      • 3. 多态的使用
        • 3.1 多态的向上转型
        • 3.2 多态的向下转型
        • 3.3 instanceof 比较操作符
      • 4. 动态绑定机制

Java 之封装、继承,多态

一、封装

1.封装的基本介绍

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

  实现封装的关键在于,绝对不能让类中的方法直接访问其他类的属性(成员变量)。程序只能通过对象的方法与对象数据进行交互。封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。这意味着一个类完全可以改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他对象就不会知道也不用关心这个类所发生的变化。


2. 封装的实现

  可以分为3步进行实现:

  1. 将属性进行私有化 privat (即不能直接修改属性)
  2. 提供一个公共的( public )set 方法,用于对属性判断并赋值。
public void SetXxx(类型 参数名) { //Xxx表示某个属性
    //可以添加数据验证的业务逻辑
    属性 = 参数名;
}
  1. 提供一个公共的 ( public )get 方法,用于获取属性的值
public 数据类型 getXxx() {
    //可以进行权限判断,Xxx表示某个属性
    return xxx;
}

案例分析:

  一个 Person 类,有姓名,年龄,工资,职位属性。在主类中设置 Person 类对象的属性,以及查看。

public class Encap {
    public static void main(String[] args) {
        Person person = new Person();//创建对象
        //调用set 方法进行属性的设置
        person.setName("熊");
        person.setAge(30);
        //······
        
        //调用get 方法查看属性
        person.getName();
        person.getAge();
        //·····
    }
}

class Person {
    private String name;
    private int age;
    private double salary;
    private String job;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        //控制 name 的长度在2-6字符之间
        if (name.length() >= 2 && name.length() <= 6)
            this.name = name;
        else {
            System.out.println("name 的长度必须在2-6个字符之间!!!");
            System.out.println("请重新设置!");
        }
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        //对设置的年龄进行判断,是否在1-120之间
        //否则设置默认值 18
        if (age >= 1 && age <= 120)
            this.age = age;
        else {
            System.out.println("年龄必须在1-120岁之间!!!");
            this.age = 18;
        }
    }

    public double getSalary() {

        //进行权限控制
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }
}

  分析:属性是私有的,所以我们不能直接修改、查看它的值,但是在创建对象的过程,调用构造器却可以直接跳过 set 方法,进行值的设置。要解决这个问题只需在构造器中也调用 set 方法。


3. 将构造器与 setXxx 方法结合

//下面只写构造器
public Person(String name, int age, double salary) {
    setName(name);
    setAge(age);
    setSalary(salary);
}

二、继承

继承: 继承的基本思想是,可以基于已有的类创建新的类。继承已存在的类就是复用(继承)这些类的方法,而且可以增加一些新的方法和字段(成员变量)。

1. 继承的基本介绍

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

  继承的示意图:

在这里插入图片描述


2. 基本语法

// class 子类 extends 父类 {
//}
//比如 Pupil 类继承 Student 类

class Pupil extends Student {
    
}

  关键字 extends 表明正在构造的新类派生于一个已存在的类。这个已存在的类称为 超类(superclass)、基类(base class) 或 父类(parent class) ;新类称为 子类(subclass)、派生类(derived class)、或孩子类(child class)。


3.继承的深入理解

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

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

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

    import pg1;
    public Base {
        private String name;
        private int age;
        
        public Base(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    import pg2;
    public class Sub {
        //具有父类的所有属性
        public Sub() {
            //如果什么都不写,默认为 super() 即调用父类的无参构造器
            super("xiong",12);//调用父类对应参数的构造器
        }
    }
    
  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 的逻辑关系。


4. 继承的本质分析(内存存在形式)

  分析:当子类继承父类,创建子类对象时,内存中到底发生了什么?

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.age);//返回的就是 39
        //System.out.println(son.getAge());//返回的就是 39
        System.out.println(son.hobby);//返回的就是旅游
    }
}

class GrandPa { //爷类
	String name = "大头爷爷";
    String hobby = "旅游";
}

class Father extends GrandPa {//父类
    String name = "大头爸爸";
    private int age = 39;
    public int getAge() {
    	return age;
    }
}
class Son extends Father { //子类
	String name = "大头儿子";
}

5. 子类创建的内存布局

在这里插入图片描述


6. super 关键字

6.1 super 的基本介绍

  super 代表父类的引用,用于访问父类的属性、方法、构造器。

6.2 基本语法
  1. 访问父类的属性,但是不能访问父类的 private 属性.

    //语法
    super.属性名;
    
  2. 访问父类的方法,但不能访问父类的 private 方法

    //语法
    super.方法名(参数列表);
    
  3. 访问父类的构造器。

    //语法
    super(参数列表);
    //只能放在构造器中,并且必须是构造器的第一条语句
    //只能出现一句
    
6.3 使用时的注意事项
  1. super 的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用 super 去访问爷爷类的成员。

    如果多个基类(上级类)中都有同名的成员,使用 super 访问遵循就近原则。A->B->C

  2. this 查找属性或方法规则:

    1. 先找本类,如果有,则调用。

    2. 如果没有,则找父类(如果有,并可以调用,则调用) 。

    3. 如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object 类 。

      提示:如果查找方法或属性的过程中,找到了,但是不能访问, 则报错, cannot access 。

      如果查找方法的过程中,没有找到,则提示方法或属性不存在。

  3. super 查找属性或方法的规则:

    //例如
    class A extends B;
    class B extends C;
    
    //从某种意义上说,C类也是A类的父类,
    //即A继承了C的属性和方法
    
    //所以 super 会先从 B 类开始查找,没有
    //就往C类查找,一直往上,直到 Object 类
    
    1. 直接从父类开始查找,如果有,则调用。

    2. 如果没有,则找上一级类(如果有,并可以调用,则调用)。

    3. 如果上一级类没有,则继续找上一级类的父类,整个规则,就是一样的,直到 Object 类。

      提示:如果查找属性或方法的过程中,找到了,但是不能访问, 则报错, cannot access。

      如果查找属性的过程中,没有找到,则提示属性或方法不存在。

6.4 super 带来的好处
  1. 调用父类构造器的好处 (分工明确,父类属性由父类初始化,子类属性由子类初始化)。
  2. 当子类中有和父类中的成员(属性或方法)重名时,为了访问父类的成员,必须通过 super。如果没有出现重名,使用 super、this、直接访问是一样的效果。
  3. super 的访问不限于父类,如果爷爷类和本类中有同名的成员,也可以使用super 去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,使用 super 访问遵循就近原则。A->B->C, 当然也需要遵守访问权限的规则。
6.5 super 和 this 的比较
No.区别点thissuper
1访问属性访问本类中的属性,如果本类中没有此属性,则从父类中继续查找从父类开始查找属性
2调用方法访问本类中的方法,如果本类没有此方法,则从父类继续查找从父类开始查找
3调用构造器调用本类的构造器,必须放在构造器的首行调用父类的构造器,必须放在子类构造器的首行
4特殊表示当前的对象子类中访问父类对象

7. 方法重写/覆盖(override)

7.1 基本介绍

  方法覆盖(重写)就是子类有一个方法和父类的某个方法的名称、返回类型、形式参数一样,那么就称为子类的这个方法覆盖了父类的方法。

7.2 使用方式、细节、注意事项

  方法重写(覆盖)需要满足以下几点:

  1. 子类的方法的形参列表、方法名称要和父类方法的形参列表、方法名称完全一样。

  2. 子类方法的返回类型和父类方法的返回类型一样,或者子类方法的返回类型是父类方法的返回类型的子类。

    //例如
    
    class String extends Object;
    //即 String 类是 Object 类的子类
    //父类 的方法:
    public Object getInfo(){
        return null;
    }
    
    //子类的方法:
    public String getInfo(){
        return null;
    }
    //则这2个方法构成方法的重写(覆盖)
    //因为String 类是 Object 类的子类
    
    
  3. 子类方法不能缩小父类方法的访问权限

    public > protect > 默认 > private
    
7.3 方法重载和方法重写(覆盖)的比较
名称发生范围方法名形参列表返回类型修饰符
重载(overload)本类中必须一样类型、个数或者顺序至少有一个不同无要求无要求
重写(override)父子类中必须一样要相同子类方法的返回类型和父类方法的返回类型一样,或者子类方法的返回类型是父类方法的返回类型的子类。子类方法不能缩小父类方法的访问范围

三、多态

1. 基本介绍

  一个对象变量可以指示多种实际类型的现象称为 多态

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


2. 具体体现

2.1 方法的多态

  重写和重载就体现多态。

//重载
public int sum(int a, int b){}
public int sum(int a){}
//调用方法,传入不同的参数调用不同的方法
//体现了多态
sum(1);
sum(3,4);

//重写
class A {
    public void say(){}
}

class B extends A {
    public void say(){}//重写了A类的方法
}

//调用过程体现了多态
A a = new A();
B b = new B();

a.say();
b.say();

2.2 对象的多态

  一些知识点的介绍:

  1. 一个对象的编译类型和运行类型可以不一致。

  2. 编译类型在定义对象时,就确定了,不能再更改。

  3. 运行类型是可以改变的。

  4. 编译类型看声明时,= 号的左边,运行类型看 = 的右边。

    //说明:
    //Dog extends Animal
    //Cat extends Animal
    
    Animal animal = new Dog();
    //animal 的编译类型为 Animal
    //运行类型为 Dog
    
    animal = new Cat();
    //animal 的运行类型变成了 Cat,
    //编译类型没有改变
    

3. 多态的使用

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

3.1 多态的向上转型
  1. 本质: 父类的引用指向了子类的对象。

  2. 语法: 父类类型 引用名 = new 子类类型();

    Animal animal = new Dog();
    
  3. 特点: 编译类型看左边,运行类型看右边。

    可以调用父类中的所有成员(包括属性和方法),但是要在遵守访问权限的前提下。

    不能调用子类中特有的成员。

    Animal animal = new Dog();
    //此时,animal 可以调用 Animal 的所有成员,遵循访问权限
    //但是,animal 不能调用 Dog 中特有的成员
    

案例讲解:

public class Ploy {
    public static void main(String[] args) {
        Animal animal = new Dog();
        
        animal.cry();//可以调用
        //animal.dogCry() 不能调用
        //因为在编译阶段,能够调用的成员由编译类型决定
        //即在 Animal 中没有 dogCry() 方法
        //在调用animal.cry() 时,
        //将会按照从子类(运行类型)开始查找方法 
        //然后调用,规则我前面我们讲的方法调用规则一致。
    }
}

class Animal {
    private String name;
    
    public void cry() {
        System.out.println("叫叫叫");
    }
}

class Dog extends Animal {
    private int age;
    
    public void dogCry() {
        System.out.println("汪汪汪");
    }
}
  1. 最终的运行效果看子类(运行效果),即调用方法时,按照从子类(运行类型)开始查找方法 ,然后调用,规则我前面我们讲的方法调用规则一致。

3.2 多态的向下转型
  1. 语法: 子类类型 引用名 = (子类类型)父类引用;

     Dog dog = (Dog)animla;
    
  2. 只能强转父类的引用,不能强转父类的对象。

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

    Dog dog = (Dog) animla;
    //即,要求 animal 指向的是 Dog 类型的对象。
    
  4. 当向下转型后,可以调用子类类型中所有的成员。

  5. 属性没有重写一说,属性的值看编译类型。

    public class PolyDetail02 {
    	public static void main(String[] args) {
    		//属性没有重写之说!属性的值看编译类型
            Base base = new Sub();//向上转型
            System.out.println(base.count);// ? 看编译类型 10
            Sub sub = new Sub();
            System.out.println(sub.count);//? 20
    	}
    }
    
    class Base { //父类
    	int count = 10;//属性
    }
    class Sub extends Base {//子类
    	int count = 20;//属性
    }
    
    

3.3 instanceof 比较操作符

  instanceOf 比较操作符,用于判断对象的 运行类型 是否为 XX 类型或 XX 类型的子类型,如果是则返回 true,否则返回 false。

  注意是看运行类型,即具体指向的对象类型。

class Base { //父类
	int count = 10;//属性
}
class Sub extends Base {//子类
	int count = 20;//属性
}

Base b = new Base();
Sub s = new Sub();
Base b0 = new Sub();

System.out.println(s instanceof Sub);//true
System.out.println(b0 instanceof Sub);//true
System.out.println(b instanceof Sub);//fale

4. 动态绑定机制

  Java 的动态绑定机制:

  1. 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定。
  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/796392.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Altium Designer软件绘制一个stm32最小系统的电路原理图

文章目录 一、安装软件二、新建工程 一、安装软件 教程: Altium Designer 24下载安装教程&#xff0c;免费汉化版&#xff0c;保姆级教程&#xff0c;附安装包 二、新建工程 1.新建项目 2.新建原理图 3.和上面一样的方法新建PCB文件 文件->原理图&#xff0c;这样文件…

产品经理-研发流程-敏捷开发-迭代-需求评审及产品规划(15)

敏捷开发是以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。 通俗来说&#xff0c;敏捷开发是一个软件开发流程&#xff0c;是一个采用了迭代方法的开发流程 简单来说&#xff0c;迭代就是把一个大产品拆分出一些最小的实现单位。完成不同的迭代就最…

组合模式(大话设计模式)C/C++版本

组合模式 C #include <iostream> #include <list> using namespace std; // 公司类... 抽象或者接口 class Company { public:Company(string name){this->name name;}virtual void Add(Company *c) 0; // 增加virtual void Remove(Company *c) 0; // 移…

docker inspect 如何提取容器的ip和端口 网络信息?

目录 通过原生Linux命令过滤找到IP 通过jq工具找到IP 使用docker -f 的过滤&#xff08;模板&#xff09; 查找端口映射信息 查看容器内部细节 docker inspect 容器ID或容器名 通过原生Linux命令过滤找到IP 通过jq工具找到IP jq 是一个轻量级且灵活的命令行工具&#xf…

几何距离与函数距离:解锁数据空间中的奥秘

几何距离&#xff1a;直观的空间度量 几何距离&#xff0c;顾名思义&#xff0c;是我们在几何学中熟悉的距离概念&#xff0c;如欧几里得距离、曼哈顿距离和切比雪夫距离等。这些距离度量直接反映了数据点在多维空间中的位置关系。 欧几里得距离&#xff1a;最为人熟知的几何距…

基于springboot+vue+uniapp的机电公司管理信息系统

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

Coze:如何使用团队空间?

你好&#xff0c;我是三桥君 团队空间&#xff0c;是一个允许我们组建团队并共享机器人、插件等资源的功能。 好的&#xff0c;让我们开始创建一个团队。我们将这个团队命名为“三桥君AI”&#xff0c;并在描述中也填写“这里是关于“三桥君AI”团队的描述”。点击确定后&…

【代码随想录】【算法训练营】【第67天】 [卡码97]小明逛公园 [卡码127]骑士的攻击

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 67&#xff0c;周六&#xff0c;ding~ [卡码97] 小明逛公园 题目描述 卡码97 小明逛公园 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#xff1a; 代码实现 C语言 Floyd 算法 [卡码…

css实现渐进中嵌套渐进的方法

这是我们想要的实现效果&#xff1a; 思路&#xff1a; 1.有一个底色的背景渐变 2.需要几个小的块级元素做绝对定位通过渐变filter模糊来实现 注意&#xff1a;这里的采用的定位方法&#xff0c;所以在内部的元素一律要使用绝对定位&#xff0c;否则会出现层级的问题&…

61、基于卷积神经网络的手写数字旋转角度预测(matlab)

1、卷积神经网络的手写数字旋转角度预测原理及流程 基于卷积神经网络的手写数字旋转角度预测是一个常见的计算机视觉问题。在这种情况下&#xff0c;我们可以通过构建一个卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;来实现该任务。以下…

SPI协议与读写串行 FLASH

SPI 协议简介 SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是美国摩托罗拉公司&#xff08;Motorola&#xff09;最先推出的一种同步串行传输规范&#xff0c;也是一种单片机外设芯片串行扩展接口&#xff0c;是一种高速、全双工、…

Vue2打包部署后动态修改后端接口地址的解决方法

文章目录 前言一、背景二、解决方法1.在public文件夹下创建config文件夹&#xff0c;并创建config.js文件2.编写config.js内容3.在index.html中加载config.js4.在封装axios工具类的js中修改配置 总结 前言 本篇文章将介绍使用Vue2开发前后端分离项目时&#xff0c;前端打包部署…

LeetCode分发糖果(贪心思路分析)

题目描述 贪心思路 思路及解法 我们可以将「相邻的孩子中&#xff0c;评分高的孩子必须获得更多的糖果」这句话拆分为两个规则&#xff0c;分别处理。 左规则&#xff1a;当 ratings[i−1]<ratings[i] 时&#xff0c;i 号学生的糖果数量将比 i−1 号孩子的糖果数量多。 …

elasticsearch集群模式部署

系统版本&#xff1a;CentOS Linux release 7.9.2009 (Core) es版本&#xff1a; elasticsearch-7.6.2 本次搭建es集群为三个节点 添加启动用户 确保elasticsearch的启动用户为普通用户&#xff0c;这里我创建了es用户用于启动elasticsearch 执行命令为es用户添加sudo权限 v…

基于AT89C51单片机超声波水位液位控制系统设计(含文档、源码与proteus仿真,以及系统详细介绍)

本篇文章论述的是基于AT89C51单片机的1616点阵LED显示器字符滚动显示设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 设计任务与要求 原理图 仿真图 代码 系统论文 资源下载 设计任务与要求…

【微信小程序知识点】手机号验证组件

手机验证组件&#xff0c;用于帮助开发者向用户发起手机号申请&#xff0c;必须经过用户同意后&#xff0c;才能获得由平台验证后的手机号&#xff0c;进而为用户提供相应的服务。 手机号验证组件分为两种&#xff1a;手机号快速验证组件以及手机号实时验证组件。 1.手机号快速…

内网对抗-基石框架篇单域架构域内应用控制成员组成用户策略信息收集环境搭建

知识点&#xff1a; 1、基石框架篇-单域架构-权限控制-用户和网络 2、基石框架篇-单域架构-环境搭建-准备和加入 3、基石框架篇-单域架构-信息收集-手工和工具1、工作组(局域网) 将不同的计算机按照功能分别列入不同的工作组。想要访问某个部门的资源&#xff0c;只要在“网络…

MES实时监控食品加工过程中各环节的安全

在实时监控食品加工过程中各环节的安全风险方面&#xff0c;万界星空科技的MES&#xff08;制造执行系统&#xff09;解决方案发挥了至关重要的作用。以下是具体如何通过MES系统实现实时监控食品加工过程中各环节安全风险的详细阐述&#xff1a; 一、集成传感器与实时监控 MES…

Prometheus + alermanager + webhook-dingtalk 告警

添加钉钉机器人 1. 部署 alermanager 1.1 下载软件包 wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz 网址 &#xff1a;Releases prometheus/alertmanager (github.com) 1.2 解压软件包 mkdir -pv …

博物馆地图导航系统:高精度地图引擎与AR/VR融合,实现博物馆数字化转型

在人民日益追求精神文化的时代下&#xff0c;博物馆作为传承与展示人类文明的璀璨殿堂&#xff0c;其重要性不言而喻。然而&#xff0c;随着博物馆规模的不断扩大和藏品种类的日益丰富&#xff0c;游客在享受知识盛宴的同时&#xff0c;也面临着“迷路”与“错过”的困扰。博物…