首页 > 编程知识 正文

什么是编程,什么叫做整元数

时间:2023-05-03 05:36:56 阅读:165711 作者:4880

即将下班的紧急任务

时钟指向六点半。 拼命的信封今天不太忙。 我想今天终于可以早点下班了。

收拾行李准备离开的时候,领队布置了新的任务,哀叹着拼命的信封没办法,乖乖地坐下了。

新任务看起来很简单。 它从CSV文件中读取数据,形成Java对象,并向外部提供API,供其他人调用。

这个CSV文件叫employee.csv,用致命的信封打开这个CSV文件,内容一目了然。

name,age,level

安迪,25,B7

Joe,22,B6

拼命信封的API需要返回ListEmployee。 很自然。 Employee班长是这样的:

公共类雇员{ privatestring name; 私有字符串; 私有级别; ……

class中的字段与csv文件标题中的列名相匹配。

这样简单的任务对一个拼命的信封来说轻而易举。 他写了一个专门分析CSV文件并创建Employee对象的EmployeeParser,不到30分钟就完成了工作。 马上下班!

还没来得及逃跑,就被领导叫住了。 “胖了,那个CSV文件中新添加了salary字段。 请快点改变你的程序! ”

name,age,level,salary

安迪,25,B7,3000

Joe,22,b 6,2500

拼命的信封勉强坐下,在Employee类中添加了salary字段,修改了EmployeeParser类,添加了对该字段的分析。

然后领导说:“添加了一个叫tax的字段! ”我听到了他在叫。

没辙了。 让我们继续修改Employee和EmployeeParser类。 这次修改结束后,领导人终于释放了他。

模板:用程序生成程序

等了两辆巴士,终于在西二旗坐上了13号线。 在拼命的信封里,我觉得明明不能保证明天就增加场地,是一项令人厌烦的繁重工作。 据说是Don't repeat yourself,怎样才能减少重复呢?

重要的是,该Java类的字段与CSV标题中的列名称相对应。 由于CSV发生了变化,因此必须修改Java类的字段和分析方法。

顺便问一下,是否可以根据CSV的列名自动生成其Employee类? 那样的话问题不就解决了吗? CSV变了,Employee类变了,多好啊!

CSV的“列名”是Java的列表,例如['name '、' age '、' level']。 如何使这个列表成为Employee Class呢?

拼命的信封鼓足干劲,想到地铁里,完全无视地铁里拥挤的人群和污浊的空气。

快下来的时候,他会一动不动,可以用模板技术。 例如,在velocity模板中定义employee.vm。

public class employee { # foreach ($ field in $ headers ) privateString$field; #end##其他代码省略}

然后,您可以编写另一个代码生成器来读取employee.csv的“标头”以形成列表,并将该列表传递给此employee.vm模板,然后输出Java类:

写下具体的代码是这样的:

velocityengineve=newvelocityengine;初始化引擎的代码缩写. template template=ve.get template (' employee.VM ' ); velocitycontextcontext=newvelocitycontext (list lt; 字符串gt; headers=readCSVHeaders (; context.put('headers ',headers ); w

riter writer = new PrintWriter(new FileOutputStream(                new File("C:\Employee.java")));           //把headers变量传递给模板template.merge(context, writer);writer.flush();    

(友情提示:可左右滑动)

(码农翻身注:这里做了简化只关注了Empployee的字段,还需要处理getter/setter方法,尤其是也需要通过模板的方法生成EmployeeParser,用来形成Employee对象。此外还有数据类型的问题。)

在小区对面的田老师红烧肉吃了一份盖饭以后,玩命的信封立刻投入到程序的编写中来,一边写一边想:我这是用程序来生成程序啊!

元编程

第二天,领导果然要加新的字段了,玩命的信封心中暗自佩服自己的自知之明,调出昨晚写的“宝贝”执行了一下,不到一秒钟,新的Employee和EmployeeParser就生成了。

下午的时候,玩命的信封洋洋得意地给Bill展示自己的工作成果,Bill说:“不错啊,都开始元编程了!”

“元编程?”

“对啊,你不是用程序来生成程序嘛,这就是一种元编程。”

玩命的信封没想到的工作居然就是高大上的“元编程”,更高兴了。

“还有,如果把CSV文件看成数据库的表,代码生成器自动生成的EmployeeParser不就相当于DAO吗?Employeeb 不就是和数据表映射的Domain对象吗? 你的代码实现了Object-relational mapping !”

就是啊,我怎么没想到,虽然距离真正的O/R Mapping还很远,但思想是一致的,大神就是厉害,看透了本质,玩命的信封暗想。

可是Bill很快给它泼了一盆冷水:“不过这种用模板生成的方式还是有些‘低级’,每次CSV文件有变化,都需要运行一下代码生成器才可以。”

“那怎么办?”

“其实吧,这个Employee的类没有必要在编译期存在,如果能在运行时动态地生成就行了。”

运行期动态生成? 玩命的信封有点懵。

“对于Java语言来说,运行期在内存中动态生成一个Class,还是有难度的,你需要透彻理解Java Class的文件格式,还需要在底层需要用ASM这样的东西去操作Java字节码。”

“文件格式和字节码?就是那些0xCAFEBABE,iload ,iadd, putfield,invokespecial ? ”  玩命的信封看过虚拟机的书,知道有很多字节码,但是操作它们形成符合要求的类,实在是难以想象。

Bill 笑道:“你可以用动态语言,比如Ruby,元编程很强大,实现你这个功能简直是小菜一碟。”

Bill很快就写出了一段代码:

#在内存中创建一个名称为Employee的类klass = Object.const_set("Employee", Class.new) names= ...读取csv文件第一行,形成数组,如 ["name","age","level"]...#对这个内存中的类进行"手术"klass.class_eval do    #现在 name,age,level...变成了这个Employee类的字段!    attr_accessor *names        #再定义一个Employee类的构造函数        define_method(:initialize) do |*values|          names.each_with_index do |name, i|          instance_variable_set("@" + name, values[i])      end    end end 

(友情提示:可左右滑动)

玩命的信封没有学过Ruby , 看到这里更懵了。

Bill看到玩命的信封发呆的样子,说道:”经过上述处理,内存中创建了一个类,如果把它的源码展示一下,你就明白了。”

#动态生成的类class Employee  #动态生成的属性,类似与java的getter方法  def name    @name  end  #动态生成的属性,类似java的setter方法  def name=(str)    @name = str  end  def age    @age  end  def age=(str)    @age = str  end  def level    @level  end  def level=(str)    @level = str  end  #动态生成的构造函数  def initialize(*values)      @name = values[0]      @age = values[1]      @level = values[2]  endend#一个使用Employee类的例子p = Employee.new("andy","22","B6")

(友情提示:可左右滑动)

(码农翻身注:对CSV文件内容的读取没有包括在其中。)

玩命的信封明白了,这个类是由数据驱动,动态生成的,CSV的header 中有多少字段,这个类就会生成多少个属性。

和自己的代码生成器比较了一下,Ruby写的这段代码更加精炼,不需要模板,没有所谓代码生成器,或者说,代码生成器和生成的类已经合二为一了。

即使是CSV文件发生了变化,也不需要额外运行代码生成器,只需要执行那段Ruby代码就行。

Bill问道:“怎么样,元编程不错吧?”

玩命的信封说道:“嗯, 这Ruby的元编程能力很强大啊,可惜的是,我们的项目都是Java的,这动态的脚本语言Ruby没法直接使用,如果是微服务,对外提供的是HTTP的API,我可以学学Ruby,单独写个Ruby项目。”

Bill说:“其实吧,编程语言中,元编程能力最强大的还属LISP,在LISP当中,程序和数据的表现形式是一致的,造就了它无以伦比的元编程能力,LISP程序可以像操作数据一样操作代码。 有人甚至说,LISP根本不是编程语言,它是编程元语言,专门为了生成程序而生。”

玩命的信封听得云里雾里,黯然道:“不知道你在说什么,太抽象了!等我学学LISP以后再回来和你讨论吧。”

(完)

码农翻身,用故事讲解技术本质, 更多精彩文章,请移步《码农翻身三年文章精华

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。