ASP.NET网页设计Ruby 的模块包括机制仓酷云
既然话题已经抄起,我打算今晚发篇博文再引导一下舆论方向,使它再火两天,抛砖引玉,而且赵劼先生一直在跟帖,使.NET阵营的我感到万分难得。在Ruby中,模块能够被其他模块包括(这里,其他模块也包含类,由于类也是模块)。经由过程包括模块,能够构建出庞大的类条理布局。本文注释了当包括一个模块时,Ruby外部都做了哪些实践的事情。上面这段Ruby代码创立了A,B,C三个模块,C包括A和B。
A=Module.newB=Module.newmoduleCincludeA,B#Inclusionisdonebythislineend在模块C中,语句includeA,B完成了模块包括的事情,该语句以A,B两个模块为作为参数,挪用了模块C的include办法。统统都那末天然。
如今,把注重力放在include办法上,它的默许完成是Module#include。依据API文档,它以相反的按次对参数一一挪用append_features办法。对应的C函数是rb_mod_include。
staticVALUErb_mod_include(intargc,VALUE*argv,VALUEmodule){inti;IDid_append_features,id_included;CONST_ID(id_append_features,"append_features");CONST_ID(id_included,"included");for(i=0;i<argc;i++)Check_Type(argv,T_MODULE);while(argc--){rb_funcall(argv,id_append_features,1,module);rb_funcall(argv,id_included,1,module);}returnmodule;}从Ruby源码来看,除对参数模块挪用append_features办法外,还紧接着挪用了included办法。以是,文档形貌得其实不完全,大概还没有更新。
append_features和included都是回调办法。而append_features办法才是真正干活的中央,Ruby经由过程这个办法将包括的逻辑转移到了被包括的模块上。这类精致的计划能让你天真地自界说包括模块的举动,既能够在收回包括举措的模块中重界说include办法,也能够从泉源动手,重界说append_features办法。
再来看看append_features的默许完成Module#append_features都做了甚么。上面是API文档上给出的源码:
staticVALUErb_mod_append_features(VALUEmodule,VALUEinclude){switch(TYPE(include)){caseT_CLASS:caseT_MODULE:break;default:Check_Type(include,T_CLASS);break;}rb_include_module(include,module);returnmodule;}这个函数对照复杂,除范例平安反省,它只是rb_include_module函数的封装,我们进一步跟到rb_include_module函数中往看看。
voidrb_include_module(VALUEklass,VALUEmodule){intchanged=0;rb_frozen_class_p(klass);if(!OBJ_UNTRUSTED(klass)){rb_secure(4);}if(!RB_TYPE_P(module,T_MODULE)){Check_Type(module,T_MODULE);}OBJ_INFECT(klass,module);changed=include_modules_at(klass,RCLASS_ORIGIN(klass),module);if(changed<0)rb_raise(rb_eArgError,"cyclicincludedetected");if(changed)rb_clear_cache();}一样,rb_include_module函数也没有做几实践的事情,只是做了一些平安方面的反省,然后把次要事情交给了include_modules_at函数。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849staticintinclude_modules_at(constVALUEklass,VALUEc,VALUEmodule){VALUEp;intchanged=0;constst_table*constklass_m_tbl=RCLASS_M_TBL(RCLASS_ORIGIN(klass));while(module){intsuperclass_seen=FALSE;if(RCLASS_ORIGIN(module)!=module)gotoskip;if(klass_m_tbl&&klass_m_tbl==RCLASS_M_TBL(module))return-1;/*ignoreifthemoduleincludedalreadyinsuperclasses*/for(p=RCLASS_SUPER(klass);p;p=RCLASS_SUPER(p)){switch(BUILTIN_TYPE(p)){caseT_ICLASS:if(RCLASS_M_TBL(p)==RCLASS_M_TBL(module)){if(!superclass_seen){c=p;/*moveinsertionpoint*/}gotoskip;}break;caseT_CLASS:superclass_seen=TRUE;break;}}c=RCLASS_SUPER(c)=rb_include_class_new(module,RCLASS_SUPER(c));if(FL_TEST(klass,RMODULE_IS_REFINEMENT)){VALUErefined_class=rb_refinement_module_get_refined_class(klass);st_foreach(RMODULE_M_TBL(module),add_refined_method_entry_i,(st_data_t)refined_class);FL_SET(c,RMODULE_INCLUDED_INTO_REFINEMENT);}if(RMODULE_M_TBL(module)&&RMODULE_M_TBL(module)->num_entries)changed=1;if(RMODULE_CONST_TBL(module)&&RMODULE_CONST_TBL(module)->num_entries)changed=1;skip:module=RCLASS_SUPER(module);}returnchanged;}include_modules_at函数做了很多事情,值得好好剖析一下。
起首,最外层的while轮回对module的先人链(ancestors)一一遍历。关于每一个module,内层的for轮回会反省module是不是已包括在klass的先人链中,假如已包括,则跳过,不然,把module拔出到c和c的父类之间。
在测试module是不是已包括在先人链的过程当中,变量superclass_seen用来判别是不是超出了一个非包括类,假如是,则不挪动拔出点。以是模块包括不会将模块插到先人链中下一个非包括类以后。
模块的拔出事情是由第31行代码完成的,它挪用rb_include_class_new函数为模块创立了一个包括类(includeclass),它以c的父类作为父类,接着又将这个包括类设置为c的父类。我们来看看rb_include_class_new函数是怎样创立包括类的。
1234567891011121314151617181920212223242526272829VALUErb_include_class_new(VALUEmodule,VALUEsuper){VALUEklass=class_alloc(T_ICLASS,rb_cClass);if(BUILTIN_TYPE(module)==T_ICLASS){module=RBASIC(module)->klass;}if(!RCLASS_IV_TBL(module)){RCLASS_IV_TBL(module)=st_init_numtable();}if(!RCLASS_CONST_TBL(module)){RCLASS_CONST_TBL(module)=st_init_numtable();}RCLASS_IV_TBL(klass)=RCLASS_IV_TBL(module);RCLASS_CONST_TBL(klass)=RCLASS_CONST_TBL(module);RCLASS_M_TBL(klass)=RCLASS_M_TBL(RCLASS_ORIGIN(module));RCLASS_SUPER(klass)=super;if(RB_TYPE_P(module,T_ICLASS)){RBASIC(klass)->klass=RBASIC(module)->klass;}else{RBASIC(klass)->klass=module;}OBJ_INFECT(klass,module);OBJ_INFECT(klass,super);return(VALUE)klass;}第4行,class_alloc创立了一个新类,并为它设置了T_ICLASS标识,有了这个标识,Ruby就会以为它是一个包括类。接着就是一系列的初始化,将新类的外部表指向模块中对应的表。最初,将新类的klass指向模块,如许,包括类就创立完成了。
第17行有个RCLASS_ORIGIN宏,我们来看看它的感化是甚么,Ruby源码中,该宏的界说以下:
#defineRCLASS_ORIGIN(c)(RCLASS_EXT(c)->origin)能够看到,它指向一个类的origin成员。复杂来讲,它猎取某个类的原始类。原始类跟模块前置有着亲切的干系。关于模块前置的更多信息,请浏览《Ruby中模块前置的完成》这篇文章。
懂得这些信息以后,我们来总结一下。为了便于形貌,我们以文章开首的那段代码作为例子,往返顾一下模块包括的全历程。
也不知道,我同学昨天说数据挖掘很好。 那么,ASP.Net有哪些改进呢? 虽然在形式上JSP和ASP或PHP看上去很相似——都可以被内嵌在HTML代码中。但是,它的执行方式和ASP或PHP完全不同。在JSP被执行的时候,JSP文件被JSP解释器(JSPParser)转换成Servlet代码,然后Servlet代码被Java编译器编译成.class字节文件,这样就由生成的Servlet来对客户端应答。所以,JSP可以看做是Servlet的脚本语言(ScriptLanguage)版。 JSP/Servlet虽然在国内目前的应用并不广泛,但是其前途不可限量。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 ASP(ActiveServerPages)是Microsfot公司1996年11月推出的WEB应用程序开发技术,它既不是一种程序语言,也不是一种开发工具,而是一种技术框架,不须使用微软的产品就能编写它的代码。 能产生和执行动态、交互式、高效率的站占服务器的应用程序。运用ASP可将VBscript、javascript等脚本语言嵌入到HTML中,便可快速完成网站的应用程序,无需编译,可在服务器端直接执行。容易编写。 对于中小项目来说.net技术是完全可以胜任,但为什么现在大型公司或网站都选择php或java呢?就是因为微软不够开放,没有提供从硬件到应用服务器再到业务应用的整套解决方案。 主流网站开发语言之PHP:PHP的全名非常有趣,它是一个巢状的缩写名称——“PHP:HypertextPreprocessor”,打开缩写还是缩写。PHP是一种HTML内嵌式的语言(就像上面讲的ASP那样)。而PHP独特的语法混合了C,Java,Perl以及PHP式的新语法。它可以比CGI或者Perl更快速地执行动态网页。 主流网站开发语言之CGI:CGI就是公共网关接口(CommonGatewayInterface)的缩写。它是最早被用来建立动态网站的后台技术。这种技术可以使用各种语言来编写后台程序,例如C,C++,Java,Pascal等。 asp.net空间的支持有:ASP.NET1.1/虚拟目录/MicrosoftFrontPage2000扩展/CDONTS,同时他的网站上也提供了Asp.net的使用详解和程序源代码,相信对使用ASP.NET编程的程序员来说会非常有用哦! 使用普通的文本编辑器编写,如记事本就可以完成。由脚本在服务器上而不是客户端运行,ASP所使用的脚本语言都在服务端上运行,用户端的浏览器不需要提供任何别的支持,这样大提高了用户与服务器之间的交互的速度。 关于ASP.NET功能上,ASP.NET比微软以前的ASP(96年出现)有更强大的library,更好的稳定性。ASP.NET可以使用.NETFramework中所有组件(也就是说.NET能实现的,ASP.NET一样能实现)。 对于中小项目来说.net技术是完全可以胜任,但为什么现在大型公司或网站都选择php或java呢?就是因为微软不够开放,没有提供从硬件到应用服务器再到业务应用的整套解决方案。 PHP的源代码完全公开,在OpenSource意识抬头的今天,它更是这方面的中流砥柱。不断地有新的函数库加入,以及不停地更新,使得PHP无论在UNIX或是Win32的平台上都可以有更多新的功能。它提供丰富的函数,使得在程式设计方面有着更好的资源。目前PHP的最新版本为4.1.1,它可以在Win32以及UNIX/Linux等几乎所有的平台上良好工作。PHP在4.0版后使用了全新的Zend引擎,其在最佳化之后的效率,比较传统CGI或者ASP等技术有了更好的表现。
页:
[1]