ASP.NET网页编程之Ruby 中模块前置的完成仓酷云
归根到底,net网页编程跨平台可以,但是要重新编写代码,否则还分什么J2EE/J2SE/J2ME呢!Ruby2.0为模块增加了一个Module#prepend办法,依据API文档的形貌,它以相反的按次对参数一一挪用prepend_features办法。和模块包括相似,会把一个模块的先人链拔出到另外一个模块的先人链中,但跟模块包括把先人链插到该模块以后纷歧样,它会把先人链插到该模块之前。我喜好把这个特征叫做模块前置。先举个例子来讲明模块前置的感化,并和模块包括作了对照。在这个例子中,类C前置了模块A和B;类D包括了模块A和B。
moduleAdeffoo;AendendmoduleBdeffoo;BendendclassCprependA,B#Prependingisdonebythislinedeffoo;CendendclassDincludeA,Bdeffoo;DendendC.ancestors#=>D.ancestors#=>C.new.foo#=>AD.new.foo#=>D
第10行,我们在C中前置了模块A和B,如许A和B就拔出到C的先人链中了。从21和22行中的正文中,我们能够看到,在C的先人链中,A和B位于C之前。而在D的先人链中,A和B位于D以后。
这就是为何第24行,C.new.foo的前往值是A,由于模块A前置于C,位于先人链的最后面,办法查找会优先找到A中的foo办法。
我们看到了模块前置的壮大的特征,但疑问也随之而来。最不言而喻的成绩是,C.ancestors为何不是从类C入手下手。要解开这个疑问,起首应当弄分明prepend办法都做了哪些事情。我们跟到源代码中往一探求竟,上面是prepend的默许完成Module#prepend对应的源代码:
staticVALUErb_mod_prepend(intargc,VALUE*argv,VALUEmodule){inti;IDid_prepend_features,id_prepended;CONST_ID(id_prepend_features,"prepend_features");CONST_ID(id_prepended,"prepended");for(i=0;i<argc;i++)Check_Type(argv,T_MODULE);while(argc--){rb_funcall(argv,id_prepend_features,1,module);rb_funcall(argv,id_prepended,1,module);}returnmodule;}
能够看到,它的举动和Module#include办法几近一样,只不外回调的办法纷歧样。这里,它回调了参数模块的prepend_features办法和prepended办法。一样,Module#prepend_features才是真正干活的中央,以是跟出来看看。
staticVALUErb_mod_prepend_features(VALUEmodule,VALUEprepend){switch(TYPE(prepend)){caseT_CLASS:caseT_MODULE:break;default:Check_Type(prepend,T_CLASS);break;}rb_prepend_module(prepend,module);returnmodule;}
它做了一些范例方面的反省,然后把事情交给了rb_prepend_module函数,我们看看rb_prepend_module函数做了甚么。
voidrb_prepend_module(VALUEklass,VALUEmodule){voidrb_vm_check_redefinition_by_prepend(VALUEklass);VALUEorigin;intchanged=0;rb_frozen_class_p(klass);if(!OBJ_UNTRUSTED(klass)){rb_secure(4);}Check_Type(module,T_MODULE);OBJ_INFECT(klass,module);origin=RCLASS_ORIGIN(klass);if(origin==klass){origin=class_alloc(T_ICLASS,klass);RCLASS_SUPER(origin)=RCLASS_SUPER(klass);RCLASS_SUPER(klass)=origin;RCLASS_ORIGIN(klass)=origin;RCLASS_M_TBL(origin)=RCLASS_M_TBL(klass);RCLASS_M_TBL(klass)=st_init_numtable();st_foreach(RCLASS_M_TBL(origin),move_refined_method,(st_data_t)RCLASS_M_TBL(klass));}changed=include_modules_at(klass,klass,module);if(changed<0)rb_raise(rb_eArgError,"cyclicprependdetected");if(changed){rb_clear_cache();rb_vm_check_redefinition_by_prepend(klass);}}
这个函数做了一些事情,我们来剖析一下。前16行都是在做一些范例反省等事情,我们跳过。从第17行入手下手剖析。
起首,宏RCLASS_ORIGIN猎取klass的origin成员,而且把它和klass对照。我们不晓得origin字段有甚么感化,我们先假定测试前提为真,即klass的origin成员指向本身。我们来剖析一下if语句中的逻辑:
[*]19举动klass创立了一个新的包括类,我们把它称为原始类;
[*]20~21行把新创立的包括类拔出到klass和klass的父类两头;
[*]22即将klass的origin成员指向了新类;
[*]接上去,23~24行把klass的办法表转移到新类中,并清空klass的办法表;
[*]最初,25行又把klass本来的办法表中的Refined办法移了返来。
剖析完if语句,我们持续行进,离开第28行。等等,你仿佛看到了熟习的工具。没错,那就是include_modules_at办法。在前一篇文章中,我们会商了这个函数,它用来包括某个模块。你几乎不敢信任本人的眼睛,明显是在前置模块,怎样俄然又酿成包括模块了?
是的,没错,它就是在包括模块。被包括的模块的先人链拔出到了klass和klass的原始类之间。因为klass外部的办法表已转移到下游的原始类中,以是拔出的地位恰好符合。Ruby经由过程这类变更,奇妙地将前置模块转化为包括模块,太棒了。
上面这个图形貌了文章开首的谁人例子中,类C中prependA,B语句实行前后的形态:
+-----++--------+Before:|C|----->|Object|+-----++--------++---------------klass----------------+||v|+-----++-----++-----++-----++--------+After:|C|----->|A|----->|B|----->|C|+---->|Object|+-----++-----++-----++-----++--------+|^||+---------------origin---------------+
正如之前剖析的那样,C就是谁人新创立的包括类,它是C的原始类。但假如是如许的话,仍是没法注释之前的疑问:为何C.ancestors不是从类C入手下手?要弄分明这个成绩,我们来看看C.ancestors是怎样事情的。
我们找到了Module#ancestors的源代码,它看起来对照复杂:
VALUErb_mod_ancestors(VALUEmod){VALUEp,ary=rb_ary_new();for(p=mod;p;p=RCLASS_SUPER(p)){if(FL_TEST(p,FL_SINGLETON))continue;if(BUILTIN_TYPE(p)==T_ICLASS){rb_ary_push(ary,RBASIC(p)->klass);}elseif(p==RCLASS_ORIGIN(p)){rb_ary_push(ary,p);}}returnary;}
该函数起首创立了一个数组,然后对遍历模块的先人链,对每一个先人,假如是包括类大概原始类指向本身,就放在前往的数组内里。别的,它还会跳过单例类。
至此,之前的疑问也失掉懂得释,C.ancestors并没有把C本身包括出来,由于它既不是包括类,也不是origin指向本身的类。而C.ancestors前往的数组中的C实际上是C的原始类,同时也是C的包括类,以是它才有C这个名字。
c语言的编译器,几乎是所有新平台都有的。因此从这点上看,c语言的程序,比其他任何语言更加容易跨平台。 大哥拜托,Java在95年就出来了,微软垄断个妹啊,服务器市场微软完全是后后来者,当年都是Unix的市场,现在被WindowsServer和Linux抢下大片,包括数据库也一样。 ASP.NET可以无缝地与WYSIWYGHTML编辑器和其他编程工具(包括MicrosoftVisualStudio.NET)一起工作。这不仅使得Web开发更加方便,而且还能提供这些工具必须提供的所有优点,包括开发人员可以用来将服务器控件拖放到Web页的GUI和完全集成的调试支持。微软为ASP.net设计了这样一些策略:易于写出结构清晰的代码、代码易于重用和共享、可用编译类语言编写等等,目的是让程序员更容易开发出Web应用,满足计算向Web转移的战略需要。 但是目前在CGI中使用的最为广泛的是Perl语言。所以,狭义上所指的CGI程序一般都是指Perl程序,一般CGI程序的后缀都是.pl或者.cgi。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。 网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项! 大哥拜托,Java在95年就出来了,微软垄断个妹啊,服务器市场微软完全是后后来者,当年都是Unix的市场,现在被WindowsServer和Linux抢下大片,包括数据库也一样。 通过这次激烈的讨论,我从大家身上学到了太多,开阔了眼界,不管是支持我的还是骂我的,都感谢你们。 现在主流的网站开发语言无外乎asp、php、asp.net、jsp等。 CGI程序在运行的时候,首先是客户向服务器上的CGI程序发送一个请求,服务器接收到客户的请求后,就会打开一个新的Process(进程)来执行CGI程序,处理客户的请求。CGI程序最后将执行的结果(HTML页面代码)传回给客户。 主流网站开发语言之PHP:PHP的全名非常有趣,它是一个巢状的缩写名称——“PHP:HypertextPreprocessor”,打开缩写还是缩写。PHP是一种HTML内嵌式的语言(就像上面讲的ASP那样)。而PHP独特的语法混合了C,Java,Perl以及PHP式的新语法。它可以比CGI或者Perl更快速地执行动态网页。 但是java靠开源打出的一片天地,特别是在微软的垄断下能打开今天的局面还是有它的生命力的。 有一丝可惜的是,这个系列太强了,Java阵营的朋友根本就是哑口无言...争论之火瞬间被浇灭,这不是我想这么早就看到的,但是值了。
页:
[1]