动态语言和静态语言比较.docx

上传人:b****1 文档编号:3029428 上传时间:2023-05-05 格式:DOCX 页数:14 大小:29.68KB
下载 相关 举报
动态语言和静态语言比较.docx_第1页
第1页 / 共14页
动态语言和静态语言比较.docx_第2页
第2页 / 共14页
动态语言和静态语言比较.docx_第3页
第3页 / 共14页
动态语言和静态语言比较.docx_第4页
第4页 / 共14页
动态语言和静态语言比较.docx_第5页
第5页 / 共14页
动态语言和静态语言比较.docx_第6页
第6页 / 共14页
动态语言和静态语言比较.docx_第7页
第7页 / 共14页
动态语言和静态语言比较.docx_第8页
第8页 / 共14页
动态语言和静态语言比较.docx_第9页
第9页 / 共14页
动态语言和静态语言比较.docx_第10页
第10页 / 共14页
动态语言和静态语言比较.docx_第11页
第11页 / 共14页
动态语言和静态语言比较.docx_第12页
第12页 / 共14页
动态语言和静态语言比较.docx_第13页
第13页 / 共14页
动态语言和静态语言比较.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

动态语言和静态语言比较.docx

《动态语言和静态语言比较.docx》由会员分享,可在线阅读,更多相关《动态语言和静态语言比较.docx(14页珍藏版)》请在冰点文库上搜索。

动态语言和静态语言比较.docx

动态语言和静态语言比较

动态语言和静态语言

有三个名词容易混淆:

1.DynamicProgrammingLanguage(动态语言或动态编程语言)

2.DynamicallyTypedLanguage(动态类型语言)

3.StaticallyTypedLanguage(静态类型语言)

FantasySoft在他文章中所提到的动态语言与静态语言实际上指的就是动态类型语言与静态类型语言。

动态语言,准确地说,是指程序在运行时可以改变其构造:

新的函数可以被引进,已有的函数可以被删除等在构造上的变化。

比方众所周知的ECMAScript(JavaScript)便是一个动态语言。

除此之外如Ruby、Python等也都属于动态语言,而C、C++等语言那么不属于动态语言。

所谓的动态类型语言,意思就是类型的检查是在运行时做的,比方如下代码是不是合法的要到运行时才判断〔注意是运行时的类型判断〕:

defsum(a,b):

returna+b

而静态类型语言的类型判断是在运行前判断〔如编译阶段〕,比方C#就是一个静态类型语言,静态类型语言为了到达多态会采取一些类型鉴别手段,如继承、接口,而动态类型语言却不需要,所以一般动态语言都会采用dynamictyping,常出现于脚本语言中。

〔idior不知道这能不能答复你对动态语言多态的疑问^_^〕

这里我需要明确说明一点,那就是,是不是动态类型语言与这门语言是不是类型平安的完全不相干的,不要将它们联络在一起!

静态类型语言的主要优点在于其构造非常标准,便于调试,方便类型平安;缺点是为此需要写更多的类型相关代码,导致不便于阅读、不明晰明了。

动态类型语言的优点在于方便阅读,不需要写非常多的类型相关的代码;缺点自然就是不方便调试,命名不标准时会造成读不懂,不利于理解等。

顺便说一下,如今有这样一种趋势,那就是合并动态类型与静态类型在一种语言中,这样可以在必要的时候取长补短,Boo就是一个很好的试验性例子。

^_^

最后说一下Boo,Boo是一个静态类型语言,虽然用ducktyping可以模拟dynamictyping,但是duck并不支持所有类型的操作替代,所以即使完全使用ducktyping也不能到达dynamictyping。

就像FantasySoft所述,TypeInference不是动态类型语言的特性,所以支持TypeInference不代表这门语言就是dynamicallytyped。

再特地为Ninputer这个VB的fans说一下VB.NET^_^,是dynamicallytyped语言。

1.动态语言DynamicallyTypedLanguage

例如:

ECMAScript(JavaScript)、Ruby、Python、VBScript、php

也叫动态类型定义语言

与静态类型定义相反,一种在执行期间才去发现数据类型的语言,

动态语言是指程序在运行时可以改变其构造:

新的函数可以被引进,已有的函数可以被删除等在构造上的变化。

动态语言的类型检查是在运行时做的。

它的优点是方便阅读,不需要写非常多的类型相关的代码;

缺点是不方便调试,命名不标准时会造成读不懂,不利于理解等。

目前java平台下的动态语言有Groovy、nice、BeanShell、Jython、JRuby、Rhino(JavaScript)、Jacl(TCL)、Bistro(SmallTalk)、Kawa(Lisp/Schema),真是越来越多了。

java下这么多的动态语言建议选择Groovy,感觉血统较为正宗,兼容Java的语法,java程序员学习起来较为容易,上手较快。

2.静态语言StaticallyTypedLanguage

例如:

C、C++、Java

也叫静态类型定义语言。

即一种在编译时,数据类型是固定的语言。

大多数静态类型定义语言强迫这一点,它要求你在使用所有变量之前要声明它们的数据类型。

在使用数据之前,我们必须首先定义数据类型,这些数据类型包括int,float,double等等。

就相当于在使用它们之前,首先要为它们分配好内存空间。

静态类型语言的主要优点在于其构造非常标准,便于调试,方便类型平安;

缺点是为此需要写更多的类型相关代码,导致不便于阅读、不明晰明了。

3.强类型定义语言

一种总是强迫类型定义的语言。

Java和Python是强迫类型定义的。

假设你有一个整数,假设不显示地进展转换,你不能将其视为一个字符串

4.弱类型定义语言

一种类型可以被忽略的语言,与强类型定义相反。

VBScript是弱类型定义的。

在VBScript中,可以将字符串'12'和整数3进展连接得到字符串'123',然后可以把它看成整数123,而不需要显示转换。

5.脚本语言

脚本语言代表一套与系统程序设计语言不同的协定。

它们牺牲执行速度和与系统程序设计语言相关的类型长度而提供更高的编程创作力和软件重用。

脚本语言更适宜在联络复杂的应用程序中进展胶着。

为了简化连接组件的工作,脚本语言被设计为无类型的,脚本语言一般是面向字符的,因为字符为许多不同的事物提供了一致的描绘。

事实上,脚本语言都是动态语言,而动态语言都是解释型语言,不管它们是不是面向对象。

静态语言的优势到底在哪?

来自robbin摘自

引用是像Java或者C#这样强类型的准静态语言在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中也有着非常强的优势

这是一个存在于大家心里常识了。

我成认我自己在潜意识里面也觉得静态强类型语言适宜开发复杂,大型系统。

而弱类型脚本语言不适宜开发太复杂,太大型的工程。

但是在参与这个讨论过程中,我突然开始置疑这个观点,事实终究是不是这样的呢?

先定义一下标准:

强类型语言(静态类型语言)是指需要进展变量/对象类型声明的语言,一般情况下需要编译执行。

例如C/C++/Java/C#

弱类型语言(动态类型语言)是指不需要进展变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。

例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/UnixShell等等。

引用观点一:

静态类型语言因为类型强迫声明,所以IDE可以做到很好的代码感知才能,因为有IDE的撑腰,所以开发大型系统,复杂系统比较有保障。

对于像Java来说,IDEA/Eclipse确实在代码感知才能上面已经非常强了,这无疑可以增加对大型系统复杂系统的掌控才能。

但是除了Java拥有这么强的IDE武器之外,似乎其他语言从来没有这么强的IDE。

C#的VisualStudio在GUI开发方面和Wizard方面很强,但是代码感知才能上和Eclipse差的不是一点半点。

至于VisualC++根本就是一个编译器而已,羞于提及Visual这个字眼。

更不要说那么多C/C++开发人员都是操起vi吭哧吭哧写了几十万行代码呢。

特别是像LinuxKernel这种几百万行代码,也就是用vi写出来的阿,够复杂,够大型,够长生命周期的吧。

引用观点二:

静态语言相比照拟封闭的特点,使得第三方开发包对代码的损害性可以降到很低。

动态语言在这点上表现的就比较差,我想大家都有过从网上下载某个JS包,然后放到工程代码里发生冲突的经历

也就是说静态类型语言可以保障package的命名空间分割,从而防止命名冲突,代码的良好隔离性。

但是这个观点也缺乏说服力。

静态类型语言中C,VB都缺乏良好的命名空间分割,容易产生冲突,但是并没有影响他们做出来的系统就不够大,不够复杂。

而VisualC++开发的DLL版本冲突也是臭名昭著的,似乎C++的命名空间没有给它带来很大的帮助。

而动态类型语言中Ruby/Python/Perl都有比较好的命名空间,特别是Python和Perl,例如CPAN上面的第三方库成吨成吨的,也从来没有听说什么冲突的问题。

诚然像PHP,JavaScript这样缺乏命名空间的动态语言很容易出现问题,但是这似乎是因为他们缺乏OO机制导致的,而不是因为他们动态类型导致的吧?

说到大型系统,复杂业务逻辑系统,Google公司很多东西都是用python开发的,这也证明了动态类型语言并非不能做大型的复杂的系统。

其实我个人认为:

动态类型语言,特别是高级动态类型语言,反而可以让人们不需要分心去考虑程序编程问题,而集中精力考虑业务逻辑实现,即考虑过程即实现过程,用DSL描绘问题的过程就是编程的过程,这方面像UnixShell,ruby,SQL,甚至PHP都是相应领域当之无愧的DSL语言。

而显然静态类型语言根本都不满足这个要求。

那静态类型语言的优势终究是什么呢?

我认为就是执行效率非常高。

所以但凡需要关注执行性能的地方就得用静态类型语言。

其他方面似乎没有什么特别的优势。

假设干评论:

1、看看yahoo吧,它是用PHP写的。

给你用JAVA也可能做不出来那样的性能。

2、我的一点感觉,动态语言足够灵敏,因此虽然它可以让人更集中精力考虑业务逻辑的实现,同时也向人工智能的方向走得更近一些,但因此它也更依赖于开发人员本身的技术功底,初学者、中级开发者,难以很好的利用它。

而静态类型语言,与我们计算机教学的根本科目〔c/pascal/basic〕延续性比较好,所以对于刚毕业的学生而言,更好承受和学习。

因此我觉得还是学习/培训/开发本钱占主要因素。

一个不太恰当的例子:

javascript的正那么表达式,虽然功能强大,但并不易理解和学习。

一般只能copy/paste来用。

所以很多情况下,还是宁愿手写标准js来处理。

3、我感觉类似Java这样的强类型的准静态语言还有一个重要的特点。

一旦程序员根本掌握了语法规那么和书写标准,写出来的程序的可读性会强很多,因为它本身的限制更多。

在一个大型系统中,Team成员之间互相可以知道对方在写什么是非常关键的,这也成为了交流的重要根底。

然而Ruby这样的语言,虽然看上去更加符合“描绘问题即解决问题〞,但是对于同一段逻辑,同样可以满足要求,写法上却差异很大。

我曾经见过用1行写出来的解决数读算法的Ruby解法,谁能看懂?

4、我更经常见到的是Java程序员屁大点事写几百行,Ruby几行就搞定了

5、静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导才能的现代语言可能可以部分减轻这个要求.

动态类型语言是在运行时确定数据类型的语言。

变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。

强类型语言是一旦变量的类型被确定,就不能转化的语言。

实际上所谓的貌似转化,都是通过中间变量来到达,本来的变量的类型肯定是没有变化的。

弱类型语言那么反之,一个变量的类型是由其应用上下文确定的。

比方语言直接支持字符串和整数可以直接用+号搞定。

当然,在支持运算符重载的强类型语言中也能通过外部实现的方式在形式上做到这一点,不过这个是完全不一样的内涵

通常的说,java/python都算是强类型的,而VB/Perl/C都是弱类型的.

不过相比于动态/静态语言的分类,强类型/弱类型更多的是一个相对的概念。

6、假设采用动态语言,单元测试上的工作量要比静态语言的多很多

robbin回这一条。

其实你忽略了一点,当使用类似RoR这样的框架的时候,应用代码量是很少的,所以相应需要测试的部分也很少,比使用静态类型语言需要测试的部分少了很多。

另外,缺少单元测试没有你说的那么恐惧。

我们如今就没有写单元测试,ruby代码都已经有6000多行了,编程也好,排错也好,一样很轻松,哪有你吹的那么恐惧。

7、商业系统的复杂在于组织上交流的困难,一个大公司,内部有个人能把商业流程搞得一清二楚就不错了,这个人还能把过程给软件人员讲清楚那简直是可遇不可求的事。

这样用ruby反而有优势了,可以快速开发,促进交流,开发出个模型出来给商务人员看看,用用,自然交流起来就容易多了。

如今一个开发人员的开发效率比以前高多了,主要原因是因为开发语言和编译器的进步,这个趋势,只会继续下去,不要抱着过去的教条不放,java也是在不断改进的,加了reflection,加了assert,加了泛型,下个版本,也要加脚本支持了。

8、其实静态类型语言,除了性能方面的考量之外,最大的优势就是可以提供静态类型平安,编译器可以检查你的每一个函数调用是不是书写了正确的名字,是不是提供了正确类型的参数。

这样一个系统,配合自定义类型的功能,可以让很多错误〔比许多人想象的要多〕在编译时就能被发现和定位。

9、我在slashdot上类似话题的讨论上曾经看到过有人抱怨动态语言,那个哥们是从事银行系统的,大概有10万行的python代码,最后因为细小隐错不断而觉得无法维护,貌似要转到java平台。

(假设把slashdot上近两年来关于ruby和python的帖子和评论看一边,大概还可以找到这个跟贴)

从这哥们的描绘来看,他的主要问题是没有单元测试或者单元测试没有到达语句覆盖或者更强的弱条件组合覆盖,从而导致某些非正常流程发生时,流经这些未被测试的语句导致语法错误而最终整个程序都挂掉.对于业务系统来说,这是非常严重的事情。

就像我前面说的那样,我自己的程序就曾经不止一次死在logging语句上,因为最初我也不测试这类语句的可通过性。

至于单元测试有没有用,三五人的工程几千行的代码是看不出来的。

其实,作坊式开发照样可以做出很多东西来,5年前国内的开发方式根本上是没有单元测试的,照样也能玩得转。

但是,就我自己的体验而言,虽然我并不遵循TDD,但单元测试是足够详尽的,而这个测试网给我的置信度(尤其是在修改代码和较大规模重构时)是之前不可想象的。

我估计上千行的程序,就可以在渐增式的单元测试中尝到好处。

10、编译器对程序员的帮助到底有多大,这个还是要应人而异的。

编译器能查出来的很多都属于打字错误,拼写错误。

对于robbin来说,即使没有编译器,检查这种错误也是小菜一碟。

可是对于经历不是很丰富的程序员来说,情况恐怕就大大不同了。

毕竟程序员经历方面差异的一个重要方面就是Debug才能和经历的差异。

对高手来说仔细读上两遍程序就能发现的错误,对一些新手来说可能会花上一两小时,这种情况我在实际工程中碰到很屡次了。

动态语言会导致开发质量下降吗?

分开CPUG以后,我的邮箱清静了很多,果断退掉一些如今已经不太关注的邮件组后,只有haskell-cafe和python社区的邮件还比较热闹。

不过这几天几位朋友都在问我这个事儿:

codebase中merge了别人的代码以后。

即便双方都没有改动同一个文件,也可能出现这种情况:

A只改动了a.py的一个方法的传参个数。

B改动了b.py,并且b.py中调用了a.py中的那个方法改动前的版本。

merge了两个文件以后,程序员根本都不会意识到如今出了问题。

原因有两个:

1.python程序员根本不用什么IDE,假设使用pydev之类,大致还能依靠IDE在merge以后看到这个错。

2.python没有编译的概念,没有时机看到编译器对这个语法问题的报错。

好了,如今只有等上线以后,通过某个事件触发这个bug了。

请问各位是杂么防范这种问题的?

unittest?

 

假设问我的意见,其实我的意见很简单的,这位楼主自己也很清楚。

是的,测试,测试再测试,计算机不变魔法。

我做过python-C#,python-Java的不同工程对接,为此同时在一个工程里用不同的语言开发过近乎对等的功能,Python比C#/Java节省一个数量级的开发量这个真的不是吹牛。

那么,你用非常之一的工作量完成了功能开发,再用非常之一的时间写对应的test代码可不可以?

就算你在自己的代码里用doctest完成了自测,工程组用unittest和其它测试脚本完成单元测试和框架级的测试,信不信你的开发量还是比java/C#要少?

相对来说,你获得了更可靠的保证,这个保证是来自开发人员明确的代码定义,而非IDE基于IDE开发者思路的通用校检,哪一个更严格更可靠?

假设你定制的质量检测脚本居然不能到达通用功能的程度,是不是应该检讨一下自己,多学习学习?

详细到这位朋友的问题,我们可以发现这样几处值得讨论的地方:

工程API变更造成merge时的冲突

这暴露了此工程缺少集成测试,无论你使用任何语言和技术,集成测试都非常重要。

搭建一个友好、“正直〞的集成测试环境,非常重要。

这种事情不应该指望某一个人的IDE,哪怕是每一个人的。

因为在团队协作中,每一个人的代码都可能不是最终发布的代码。

应该把提交和上线当做一件严肃的事,上线之前一定要集成测试,类似API变更冲突这种错误大多是可以防止的。

指望IDE驱动编译器发现错误

另一方面,每个人提交完以后,应该再update一次,然后在本地集成测试一次。

这里IDE有支持的话应该积极使用,虽然不能完全防止错误,但是有做比没做好。

同时我们也应该知道,这个功能用IDE能完成,用脚本也一样可以,而且不会更费事。

我在开发socrates工程时就是这样做的。

事实上因为在python中写测试更简单,我用起来感觉要比在C#/CPP中爽很多。

所以这个问题不在于用不用IDE,而在于你有没有心去做这样的事。

还是那句话,用python/ruby什么的,就算你加上写测试,还是省力的。

对动态语言的类型转换错误太过敏感

当然,我们应该成认,动态类型语言不检查传递的参数,确实会引发一些风险,但是在我接触过的工程中,真正要面对的总是资源管理问题和逻辑错误,不管哪一种语言哪一种应用,类型错误少之又少。

一个数量级以上的性能提升,付出这样的代价相当值得。

静态语言如今也倾向于尽可能由编译器发现类型,越来越少的要求用户显式给出约束。

包括类型系统最为严苛的haskell,它也鼓励用户编写出编译器可以自动感知类型的代码。

假设想兼顾书写的便利和静态类型语言的平安感,Java程序员其实可以试试scala,最近我也在学习这个语言,是个非常有爱的好东西。

无论用哪一种语言,最终写代码的仍然是人。

详细到这个贴子中出现的问题,我认为首先要检讨团队管理过程,语言的问题只是个表像。

无论动态语言还是静态语言,积极建立测试体系才是正道,无论用Java还是Python,CPP还是ruby。

尤其在线系统,要有一个集成测试的环境。

传统的静态类型语言可以防止此类小概率错误的一部分发生可能,而运用动态语言或现代的,更为智能的静态语言,那么可以将更多的时间省下来,建立完好的质量管理体系,在更高的层面上消灭这种错,在应用工程开发中,后者胜出。

动态语言会淘汰静态语言吗?

上一篇博客动态语言会导致开发质量下降吗?

,尽管没有我想像的那么多争议,但还是如期引发了一些误解。

有一些朋友指出动态语言,详细来说是Python中的各种问题。

这些我认为是大部分是正确的。

我写上文的用意,在于讨论动态语言使用过程中,关于质量控制的必要性,以及其引发的性价比方面的争议。

这并不表示动态语言全面的优于静态语言,更不表示静态语言会被动态语言全面的取代。

进一步,这里我简单的说一下,我所认识到的,静态语言相对的优越性,和存在意义。

这里首先我表达一下我一贯的观点:

计算机不会魔法。

详细来说两方面,一是离机器越近,性能上越有可能到达更快;二是目前的机器模型,总是以线性方式管理数据的〔值得吐槽的是在操作系统以上,文件分区系统也总是这样干的,更底层能否以哪怕是极座标方式,直接在二/三维空间上定位访问,而非扇区、柱面、簇这种形式,我不清楚,有待方家指点〕。

线性管理信息带来的效应就是:

基于线性数据构造,或以地址访问信息的编程工具,通常来说会比基于字典构造的更快,至少有更大的优化空间。

而静态语言的话,编译时我们已经确定了对象的构造和尺寸〔动态尺寸的内容可以通过引用管理〕,这是动态语言无法做到的。

动态语言的对象构造,总是基于字典构造,要兼顾对象构造在运行时发生改变的问题。

这使得它的数据管理总是要比直接地址访问要多上那么一层。

这也是甚少见到动态语言编译器的原因。

流行的动态语言,几乎都是解释/字节码平台,甚至,最常见的Python/Ruby等等语言,几乎都有饱受批评的GIL〔GlobalInterpreterLock〕。

以Python社区的经历来说,多年来出现的数个无GIL的C-Python实现,单核性能都不如如今的官方版本。

Jython和IronPython那么是得益于JVM和CLR,这两个久经经考验的虚拟机平台,它们的first-classlanguage都是静态编译型语言〔尽管其主流编译器生成的是字节码,但是通常我们都视Java和C#为编译语言〕。

为Perl社区期待多年的Perl6,至今还没有真正的发布〔其虚拟机Parrot虽然已经发布,但受制于主力语言实现进度,如今还没有得到足够的实战验证〕。

为动态语言实现一个高性能的,特别是并行的高性能环境,难度之高,可见一斑。

根本上说,在当前的硬件模型上,想要以非线性的方式管理信息,动态伸缩,动态修改构造,非常的不容易。

举一个例子,候捷老师有一个讲座,是以windows95为例,詳細讲解malloc/free的底层实现,有听过的朋友应该对操作系统动态管理内存资源的复杂程度有所体会。

类似的内容在很多操作系统之类的技术书籍中都有介绍,有兴趣的朋友可以找来看看,我手边有一本?

Unix系统编程?

就有相关的内容。

这类问题涉及比较深化的底层问题,我不是科班出身,这方面比较外行,讲的不是很好,不过有兴趣的朋友可以深究一下,会发现这事儿比看起来要费事得多。

想要让动态语言到达静态化的性能,是件相当有挑战的事。

Google的ProtocolBuffer协议,也是基于静态模型的。

现代的静态语言,搞了很好的“假装〞,使它写起来可以非常的有“动感〞,例如C#3,Scala等,但究其本质,它们代码中涉及的类型,仍然是可以编译期确定的。

我所接触过的语言中,此类功能最有历史的应该是Haskell,而它是通过一个非常严苛的数学体系来推导类型,在此过程中,还是时有需要程序员显式声明函数类型,才能完成编译。

静态语言在变得越来越友好敏捷,动态语言在越来越快,但是两者之间的分界,仍然相当的明晰,静态语言更快,更具优化潜力。

动态语言更灵敏,更具表达才能。

这是两者不能被互相取代的根本原因。

当然,性能问题并不简单,动态语言在宏观上往往没有具部的测试结果看起来那么慢,这是因为要表达复杂的业务逻辑,往往需要复杂的数据构造和访问代码,这些复杂的数据内容,要随着用户的访问不断变化。

要实现这一切,假设使用静态语言,就要关注动态数据构造的实现,假设使用的是没有GC的开发技术,还要关注内存资源的回收,确实会出现绕了一大圈儿,结果实现的系统还没有现成的动态语言快的现像〔尽管这不是普遍的〕。

更何况现实中总是以线性读写的IO接口,更严重拉平了不同语言之间的性能差异。

所以如今比较得到认可的实现方式往往是以动态语言实现工程,然后,假设有需求,也有这个本钱负担,就以静态语言优化性能瓶颈。

当然,上述的形式往往用在效劳器型的工程中,在GUI环境中,要与显示器、鼠标键盘等人机交互环境频繁的互动,这个资源付出非常的大,加上在CPP等静态语言大行的时代,GUI开发已经相当成熟,技术力量沉积的历史原因,这个领域仍然是以静态的、编译型的语言为主力。

最多是为了提交二次开发才能,提供动态语言调用的接口,或嵌入一个解释环境,有限的利用。

其实即使是效劳器环境,随着互联网的开展,性能问题也正在越来越突出。

我就遇到过某个简单逻辑的功能,使用Python怎样都无法优化到理想的程度,最终用Objective

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 求职职场 > 社交礼仪

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2