引言
JavaScript 早在发明初期时,仅用来进行简单的表单数据验证,但随着 Web 2.0 技术的蓬勃发展,尤其是近年来 Ajax 的异军突起,JavaScript 如今已成为 Internet 上最流行的脚本语言,用其开发的 web 应用也因高互动性极大的丰富了用户体验。而与此同时,当前的富英特网应用程序的代码量也产生了爆炸式的增长,因此利用面向对象的 JavaScript 编程,构建具有高复用性、易维护、易扩展性、健壮的浏览器端应用,具有重要意义。
与高级语言 Java、C++ 等不同,JavaScript 本身并不是面向对象的语言,没有明确的类的概念,但可以通过核心语言来构建对象系统,模拟类及类的继承。但显然,构建类定义系统并不简单,庆幸的是,dojo.declare 可以帮助我们完成这项复杂的工作。本文将详细讲解如何利用 dojo.declare 定义类,实现单继承及多继承,及其他面向对象特性。为了更深入的理解 dojo.declare 模拟继承的原理,首先介绍原生 JavaScript 两种基本的继承方式,对象冒充及基于原型的继承。
JavaScript 继承方式
关于继承可以朴素的理解为,通过继承,子类可以复用父类的方法,以达到代码重用。JavaScript 可用多种方式模拟继承,本文先举例介绍各种方法,后对比分析优缺点。
对象冒充
在 JavaScript 中,构造函数也和普通的函数一样,可以被赋值和调用,对象冒充通过此原理来模拟继承。
清单 1. 对象冒充示例
Function ClassA(name)
{
this.name = name;
this.sayHello = function(){
alert("Hello, " + this.name);
}
}
Function ClassB(name,time)
{
this.newMethod = ClassA;
this.newMethod(name);
delete this.newMethod;
this.time = time;
this.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
}
var objA = new ClassA("Tom");
var objB = new ClassB("Jerry","11:30am");
objA.sayHello(); // output is : "Hello,Tom"
objB.sayHello(); // output is : "Hello,Jerry"
objB.sayGoodbye();// output is : "Goodbye Jerry, it ’ s 11:30am now!"
|
如清单 1 所示,将 ClassA 的构造函数赋值为 ClassB 的一个普通方法,然后调用它,由于此时 this 指向的是 ClassB 的实例,那么 ClassB 的实例就会收到 ClassA 构造函数中定义的属性和方法,从而达到了继承的效果。
需要注意的是,应及时删除临时引用(this.newMethod),以防止 ClassB 更改 ClassA 类对象的引用。因为对临时引用(this.newMethod)的更改,也会导致 ClassA 的结构变化。并且 ClassB 的所有新属性和新方法,应该在删除临时引用后定义,否则,可能会覆盖父类的相关属性和方法。
认识到对象冒充的本质后,可以采用 JavaScript 中的 call 或者 apply 函数达到同样的效果,如清单 2 代码所示。其原理也是在调用 ClassA 的构造函数时,将 this 指向 ClassB 的实例。
清单 2. 利用 call() 实现对象冒充
Function ClassB(name,time)
{
ClassA.call(this,name); // 或者 ClassA.apply(this,[name]);
this.time = time;
this.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
}
|
基于原型的继承
JavaScript 中的每个对象都包含一个原型对象(prototype),指向对某个对象的引用,而由于原型对象本身也是对象,则也会包含对它的原型的引用,由此构成一条原型链。原型链终止于内建 Object 类的原型。当要读取某个对象的属性或方法时,JavaScript 首先在该对象中查找,若没有找到,便在该对象的原型中继续查找,若仍未找到,便顺着原型链继续在原型的原型中查找,直到查找到或到达原型链的尽头。这样的系统被称为原型继承。而基于原型的继承,则是指利用了 prototype 或者说以某种方式覆盖了 prototype,从而达到属性及方法复用的目的。如下所示:
清单 3. 原型继承示例
Function ClassA()
{
this.name = "";
this.sayHello = function(){
alert("Hello, " + this.name);
}
}
Function ClassB(){};
ClassB.prototype = new ClassA();
var objB = new ClassB();
objB.name = "Jerry";
objB.sayHello(); //output: "Hello,Jerry";
|
示例代码中将 ClassB 的 prototype 指向 ClassA 的实例,其原型链如图 1 所示,这样 ClassB 便拥有了 ClassA 所有的属性和方法,可以自由的赋值和调用。
图 1. ClassB 原型链
对比
对象冒充和基于原型的方式都可以让子类复用父类的代码以模拟继承,但这两种方法均各有利弊。
利用对象冒充,可以方便的实现多继承,只需要对所有需要继承的父类重复进行赋值流程便可。但这样却有着有明显的性能缺陷,因为在利用对象冒充模拟继承时,每个实例都会拥有一份父类成员变量和方法的副本,而成员方法只是一段对变量操作的可执行文本区域而已,这段区域不用为每个实例复制一份,所有的实例均可共享,这就造成了对内存资源的极度浪费。并且对象冒充也无法继承 prototype 域的变量和方法。
而基于原型的继承则可以使子类拥有一条完整的原型链,并且所有子类实例的原型都指向同一引用,相对于对象冒充,可极大的节省内存开销。但基于原型继承的缺陷也相当明显,就是父类的构造函数不能有参数,因为对子类 prototype 域的修改需在声明子类对象之后才能进行,而用子类构造函数的参数去初始化父类构造函数的属性是无法实现的。
因此可以结合二者的优点,采用混合的方式模拟继承,即用对象冒充的方式给属性赋值,用原型链的方式继承方法,示例代码如下:
清单 4. 混合方式继承示例
Function ClassA(name){
this.name = name;
}
ClassA.prototype.sayHello = function(){
alert("Hello, " + this.name);
}
Function ClassB(name,time){
ClassA.call(this, name);
this.time = time;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
var objA = new ClassA("Tom");
var objB = new ClassB("Jerry","11:30am");
objA. sayHello();// output is: "Hello, Tom"
objB.sayHello(); // output is: "Hello, Jerry"
objB.sayGoodbye();//output is: "Goodbye Jerry,it ’ s 11:30am now !"
|
dojo.declare 详解
由上章的介绍可以发现,使用原始的 JavaScript 定义类并实现继承并不是件简单的工作,幸运的是 dojo.declare 提供了一整套的类定义机制,使我们可以像在高级语言中定义类一样,简单明确的完成类的声明。接下来将详细讲解 dojo.delcare 的用法及原理。
运用 dojo.declare 定义类
dojo.declare 方法的 API 如下,它有如下三个参数:
清单 5. dojo.declare 参数定义
dojo.declare(/*String*/ className,
/*Function | Function[]*/ superclass,
/*Object*/ props )
|
- className: 是要要申明的类的类名,也就是创建的构造函数的名称。
- superclass:所要继承的父类,此参数可为 null,表示没有父类,或者为一个父类,或为多个父类的数组,会在后续小节内详述。
- props:散列体,由名、值(key, value)对组成,这个散列体将被添加到定义的类的原型对象中,也即为定义的类被其所有实例共享的属性及方法。其中,key :constructor 为保留字,此函数用来初始化新对象。
如清单 6 所示,我们用 dojo.declare 定义了一个名为 ClassX 的类,父类为空,即无父类,类的每个实例都有属性 messageX,在调用 constructor 函数初始化新对象时赋值,并为类的原型设置了 sayMessageX 方法。
清单 6. dojo.declare 定义类示例
dojo.declare(
"ClassX", // 类的名字
null, // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageX: null,
constructor: function(msgX){
this.messageX = msgX;
},
sayMessageX: function(){
alert("hi, this is " + this. messageX);
}
}
);
|
定义类 ClassX 后,便可以使用了,由示例代码可见,类 ClassX 的对象既是 ClassX 的实例也是 Object 的实例。
清单 7. ClassX 使用示例
var objX = new ClassX("X");
objX. sayMessageX(); //output: "hi, this is X"
objX instanceof ClassX; //true
objX instanceof Object;//true
|
此处以 ClassX 为例,介绍由 dojo.declare 申明的类的原型对象空间,如图 2 所示,主要包括以下属性:
- declaredCalss: 函数名,即传给 dojo.declare 的第一个参数。
- _constructor:类的初始化函数,即 props 中的 constructor 函数,当创建一个新对象时,由 dojo.declare 生成的构造函数自动调用此函数初始化所有的实例属性。
- constructor:由 dojo.declare 为类生成的构造函数。
- inherited:运用此方法可以调用父类的同名函数。
- props 中定义的所有属性及方法,此处包括 messageX 和 sayMessageX。
- 由于 ClassX 没有父类,则其原型的原型指向根原型。
图 2. ClassX 原型对象空间
单继承
假设有一个类 ClassZ,希望继承 ClassX,则可以用 dojo.declare 定义如下:
清单 8. 利用单继承定义 ClassZ 示例
dojo.declare(
"ClassZ", // 类的名字
ClassX, // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageZ: null,
constructor: function(msgX,msgZ){
this.messageZ = msgZ;
},
sayMessageZ: function(){
alert("hi, this is " + this.messageZ);
}
}
)
var objZ = new ClassZ("X","Z");
objZ.sayMessageX();//output is: "hi, this is X"
ojbZ.sayMessageZ();//output is: "hi, this is Z"
|
如代码所示,为了继承父类,仅需将父类作为 dojo.declare 的第二个参数就可以了。但其实 dojo.declare 帮我们做了以下两个工作:
- 构造新类的原型对象,并将其原型指向父类的原型。
- dojo.delcalre 为 ClassZ 生成的构造函数,将会先调用父类的构造函数,再调用子类的构造函数,这点与高级语言在继承中调用构造函数的顺序一致。如创建 ClassZ 对象,需执行类似以下的代码,这非常类似于上一章节中提到的混合继承方式。
清单 9. 创建 ClassZ 实际执行代码 ( 单继承 )
Var objZ = new ClassZ("X","Z");
ClassX.apply(this,["X","Z"]);
ClassZ._constructor.apply(this, ["X","Z"]);
|
ClassZ 的原型对象空间如下图所示,可以看到 ClassZ 类的原型引用了 ClassX 类的原型对象,则当如清单 8 中调用 ClassX 的方法时,首先将在 ClassZ 类的原型空间查找,在未查找到后,继而在 ClassX 的原型查找,查找到后调用。
图 3. ClassZ 原型对象空间 ( 单继承 )
多继承
假设有 ClassY 定义如下:
清单 10. ClassY 示例
dojo.declare(
"ClassY", // 类的名字
null, // 父类
{
messageY: null,
constructor: function(msgY){
this.messageY = msgY;
},
setMessageY: function(msgY){
this.messageY = msgY;
},
sayMessageY: function(){
alert("hi, this is " + this.messageY);
}
}
);
|
而 ClassZ 希望同时继承自 ClassX 及 ClassY,则可由 dojo.declare 定义如下:
清单 11. 利用多继承定义 ClassZ 示例
dojo.declare(
"ClassZ", // 类的名字
[ClassX,ClassY] // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageZ: null,
constructor: function(msgX,msgY,msgZ){
this.messageZ = msgZ;
this.setMessageY(msgY);
},
sayMessageZ: function(){
alert("hi, this is " + this.messageZ);
}
}
);
|
虽然我们仅将需继承的父类放入数组传递给 dojo.declare, 但这样定义出的类 ClassZ 却拥有 ClassX 与 ClassY 的全部功能。此处关于 ClassZ 初始化函数的详细讲解见下节。需注意的是,当将数组作为 superclass 参数时,仅第一个元素为新类的父类,之后的类会被当做为聚合类。聚合类中的属性和方法会被拷贝到新类中,以使新类具有聚合类的功能,从而达到模拟继承的效果。对于这种拷贝,除非属性保存的是数字,字符串,布尔,或者 null,否则均为引用拷贝。
下图为 ClassZ 的原型对象空间,由图可见,ClassZ 原型链的上一级指向的是 ClassX 的原型,则说明 ClassX 为其父类,而其原型中包含的 setMessageY 和 sayMessageY 函数则指向与 ClassY 原型对象中相同函数对象。
图 4. ClassZ 原型对象空间 ( 多继承 )
由于 dojo.declare 是用聚合类来模拟多继承,则 ClassZ 的实例是 ClassZ ,ClassX 类以及 Object 类的实例,但不会是 ClassY 类的实例,如下代码所示:
清单 12. ClassZ 使用示例
var objZ = new ClassZ("X","Y","Z");
objZ.sayMessageZ();//output is : "hi, this is Z"
var check;
check = objZ instanceof ClassZ; // true
check = objZ instanceof ClassX; // true
check = objZ instanceof Object; // true
check = objZ instanceof ClassY; // false
|
预处理构造函数参数
对于继承和聚合,若子类,父类或聚合类之间的构造函数签名不同,则需要预处理构造函数的参数。
例如,ClassX(清单 6),ClassY(清单 10)及 ClassZ(清单 11) 的构造函数签名分别为:(msgX), (msgY), (msgX,msgY,msgZ) ; 当我们创建 ClassZ 的实例时,在默认情况下,dojo.declare 会按序先将参数传递给父类的构造函数,然后传递给聚合类的构造函数,最后传递给子类的初始化函数,如以下代码所示:
清单 13. 创建 ClassZ 实际执行代码 ( 多继承 )
var objZ = new ClassZ("X","Y","Z");
ClassX.apply(this,["X","Y","Z"]);
ClassY.apply(this, ["X","Y","Z"]);
ClassZ.prototype._constructor.apply(this, ["X","Y","Z"]);
|
由于 ClassX 仅需一个参数,因此可以忽略掉后两个参数“Y”,“Z”,被正确的初始化。而 ClassY 虽然也仅需一个参数,但传递给它的第一个参数却是“X”,因此它会将“X”当做“Y”,而被错误的初始化。为纠正这个错误,我们在 ClassZ 的构造函数中显示的调用了 setMessageY (msgY) 这个方法。 ClassZ 的初始化函数也可正确的接收这三个参数,它首先正确的初始化了 msgZ,后初始化 ClassY 类的实例变量。但由于父类及聚合类的构造函数会先于子类的初始化函数调用,则在 ClassZ 的初始化函数调用 setMessageY(msgY) 之前,属性 msgY 都被初始化错误。
大多数情况下,都可运用这种方法修复错误的初始化,但不正确的初始化有可能会带来一些坏的副作用,如抛出异常。
将散列表作为构造函数的参数则是一种更简单安全的做法。如,通过以下方式创建 ClassZ 的实例(清单 13 中第一行),需将本文中 ClassX,ClassY,ClassZ 的初始化函数重写如下:
清单 14. 初始化函数示例
var ClassZ = new ClassZ({msgX:"X",msgY:"Y",msgZ:"Z"});
// ClassX
constructor: function(args){
if(args && args.msgX)
this.msgX = args.msgX;
}
// ClassY
constructor: function(args){
if(args && args.msgY)
this.msgY = args.msgY;
}
// ClassZ
constructor: function(args){
if(args && args.msgZ)
this.msgZ = args.msgZ;
}
|
则通过此方式创建 ClassZ 的实例的过程中,不会有任何的初始化错误出现,并且此种方式也消除了对参数顺序的依赖。当参数个数过多时,将会是个不错的选择。
结束语
本文详细讲解了 dojo.declare 的各种用法,并通过实例及图解深入分析了其通过原型链及聚合类模拟面向对象的继承的原理。dojo.declare 不仅给 JavaScript 开发人员提供了一种自然的方式简洁明了的创建类,而且可通过已定义的类来组合新类,使人们可以更简单高效的复用代码。相信通过 dojo.declare,可以使您开发出更易扩展、易维护、更健壮的 web 应用程序!
分享到:
相关推荐
1、文件内容:ibus-table-chinese-erbi-1.4.6-3.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ibus-table-chinese-erbi-1.4.6-3.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
选择Java后台技术和MySQL数据库,在前台界面为提升用户体验,使用Jquery、Ajax、CSS等技术进行布局。 系统包括两类用户:学生、管理员。 学生用户只要实现了前台信息的查看,打开首页,查看网站介绍、自习室信息、在线留言、轮播图信息公告等,通过点击首页的菜单跳转到对应的功能页面菜单,包括网站首页、自习室信息、注册登录、个人中心、后台登录。 学生用户通过账户账号登录,登录后具有所有的操作权限,如果没有登录,不能在线预约。学生用户退出系统将注销个人的登录信息。 管理员通过后台的登录页面,选择管理员权限后进行登录,管理员的权限包括轮播公告管理、老师学生信息管理和信息审核管理,管理员管理后点击退出,注销登录信息。 管理员用户具有在线交流的管理,自习室信息管理、自习室预约管理。 在线交流是对前台用户留言内容进行管理,删除留言信息,查看留言信息。
面向基层就业个性化大学生服务平台(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 面向基层就业个性化大学生服务平台(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 面向基层就业个性化大学生服务平台中的管理员角色主要负责了如下功能操作。 (1)职业分类管理功能需求:对职业进行划分分类管理等。 (2)用户管理功能需求:对用户信息进行维护管理等。 (3)职业信息管理功能需求:对职业信息进行发布等。 (4)问卷信息管理功能需求:可以发布学生的问卷调查操作。 (5)个性化测试管理功能需求:可以发布个性化测试试题。 (6)试题管理功能需求:对测试试题进行增删改查操作。 (7)社区交流管理功能需求:对用户的交流论坛信息进行维护管理。 面向基层就业个性化大学生服务平台中的用户角色主要负责了如下功能操作。 (1)注册登录功能需求:没有账号的用户,可以输入账号,密码,昵称,邮箱等信息进行注册操作,注册后可以输入账号和密码进行登录。 (2)职业信息功能需求:用户可以对职业信息进行查看。 (3)问卷信息功能需求:可以在线进行问卷调查答卷操作。 (4)社区交流功能需求:可以在线进行社区交流。 (5)个性化测试功能需求:可以在线进行个性化测试。 (6)公告资讯功能需求:可以查看浏览系统发布的公告资讯信息。 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
三菱Fx3u程序:自动检测包装机电机控制模板,PLC脉冲与伺服定位,手自动切换功能,三菱Fx3u程序:自动检测包装机电机控制模板——涵盖伺服定位与手自动切换功能,三菱Fx3u程序,自动检测包装机。 该程序六个电机,plc本体脉冲控制3个轴,3个1pg控制。 程序内包括伺服定位,手自动切,功能快的使用,可作为模板程序,很适合新手。 ,三菱Fx3u程序; 自动检测包装机; 六个电机; PLC脉冲控制; 伺服定位; 手自动切换; 功能快捷键; 模板程序。,三菱Fx3u PLC控制下的自动包装机程序:六电机伺服定位与手自动切换模板程序
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
计及信息间隙决策与多能转换的综合能源系统优化调度模型:实现碳经济最大化与源荷不确定性考量,基于信息间隙决策与多能转换的综合能源系统优化调度模型:源荷不确定性下的高效碳经济调度策略,计及信息间隙决策及多能转的综合能源系统优化调度 本代码构建了含风电、光伏、光热发电系统、燃气轮机、燃气锅炉、电锅炉、储气、储电、储碳、碳捕集装置的综合能源系统优化调度模型,并考虑P2G装置与碳捕集装置联合运行,从而实现碳经济的最大化,最重要的是本文引入了信息间隙决策理论考虑了源荷的不确定性(本代码的重点)与店铺的47代码形成鲜明的对比,注意擦亮眼睛,认准原创,该代码非常适合修改创新,,提供相关的模型资料 ,计及信息间隙决策; 综合能源系统; 优化调度; 多能转换; 碳经济最大化; 风电; 光伏; 燃气轮机; 储气; 储电; 储碳; 碳捕集装置; P2G装置联合运行; 模型资料,综合能源系统优化调度模型:基于信息间隙决策和多能转换的原创方案
IPG QCW激光模块电源驱动电路设计与实现:包含安全回路、紧急放电回路及光纤互锁功能的多版本原理图解析,IPG QCW激光模块电源驱动电路设计与实现:含安全回路、紧急放电及光纤互锁等多重保护功能的原理图解析,IPG QCW激光模块电源驱动电路, 包含安全回路,紧急放电回路,光纤互锁回路等, 元件参数请根据实际设计适当调整,此电路仅供参考,不提供pcb文件 原理图提供PDF和KICAD两个版本。 ,IPG激光模块; QCW激光电源驱动; 安全回路; 紧急放电回路; 光纤互锁回路; 原理图PDF和KICAD版本。,IPG激光模块电源驱动电路图解:含安全与紧急放电回路
基于LSSVM的短期电力负荷预测模型及其性能评估:结果揭露精确度与误差分析,LSSVM在短期电力负荷预测中的结果分析:基于均方根误差、平均绝对误差及平均相对百分误差的评估。,LSSVM最小二乘支持向量机做短期电力负荷预测。 结果分析 均方根误差(RMSE):0.79172 平均绝对误差(MAE):0.4871 平均相对百分误差(MAPE):13.079% ,LSSVM(最小二乘支持向量机);短期电力负荷预测;均方根误差(RMSE);平均绝对误差(MAE);平均相对百分误差(MAPE),LSSVM在电力负荷短期预测中的应用及性能分析
1、文件内容:libmtp-examples-1.1.14-1.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/libmtp-examples-1.1.14-1.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
资源内项目源码是均来自个人的课程设计、毕业设计或者具体项目,代码都测试ok,都是运行成功后才上传资源,答辩评审绝对信服的,拿来就能用。放心下载使用!源码、说明、论文、数据集一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 4、如有侵权请私信博主,感谢支持
2023-04-06-项目笔记-第四百一十六阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.414局变量的作用域_414- 2025-02-21
MINIST数据集和春风机器学习框架
1、文件内容:ibus-table-chinese-wu-1.4.6-3.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ibus-table-chinese-wu-1.4.6-3.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
宿舍管理系统(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 系统拥有管理员和学生两个角色,主要具备系统首页、个人中心、学生管理、宿舍信息管理、宿舍分配管理、水电费管理、进入宿舍管理、出入宿舍管理、维修信息管理、卫生信息管理、考勤信息管理、留言板、交流论坛、系统管理等功能模块。 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
人凤飞飞凤飞飞是粉色丰富
2024蓝桥杯嵌入式学习资料
image_download_1740129191509.jpg
基于Multisim仿真的带优先病房呼叫系统设计(仿真图) 设计一个病房呼叫系统。 功能 (1)当有病人紧急呼叫时,产生声,光提示,并显示病人的编号; (2)根据病人的病情设计优先级别,当有多人呼叫时,病情严重者优先; (3)医护人员处理完当前最高级别的呼叫后,系统按优先级别显示其他呼叫病人的病号。
基于STM32F103的3.6kW全桥逆变器资料:并网充电放电、智能切换与全方位保护方案,基于STM32F103的3.6kW全桥逆变器资料:并网充电放电、智能控制与全方位保护方案,逆变器光伏逆变器,3.6kw储能逆变器全套资料 STM32储能逆变器 BOOST 全桥 基于STM32F103设计,具有并网充电、放电;并网离网自动切;485通讯,在线升级;风扇智能控制,提供过流、过压、短路、过温等全方位保护。 基于arm的方案区别于dsp。 有PCB、原理图及代码ad文件。 ,逆变器; 储能逆变器; STM32F103; 3.6kw; 485通讯; 全方位保护; 智能控制; 方案区别; PCB文件; 原理图文件; ad文件。,基于STM32F103的3.6kw储能逆变器:全方位保护与智能控制