2.3 自己动手写函数 用Lpc写Object的函数,是为了表现这个Object的特性。这个特性的 函数实际上就是一些代码按顺序排列,排列的顺序决定了这个函数。一 个函数被调用,函数的代码就按照函数定义中代码按顺序执行。在 eventPrintValue()中,下面这个语句: ----- x = add(2, 2); ----- 必须在 efun: write() 之前调用,如果你想看到正确的结果。 为了返回这个函数执行后的值,必须这么做:使用 "return" 指令和后 面跟着和这个函数数据类型一样的一个值。在上面的 add(),这个指令是 "return ( x + y );",( x + y )的值就是返回给 eventPrintValue() 以及赋给 x 的那个值。更进一步的说,"return" 结束当前函数的执行 并把控制权返回给调用它的那个函数。实际上,return 可以返回跟在 它后面的一个表达式的值。如果想停止一个类型为void的函数的执行, 只要简单使用 "return;",不返回任何值。强调一点,想要返回的表达 式的值的数据类型 必须 和函数自己的数据类型一致。 那到底如何写一个函数(lfun)? 一个函数定义通常按次序有下面部分: 1) 函数返回数据类型 2) 函数名 3) 以 ( 开始,以 ) 结束的函数列表 4) 一个 { 标志这个函数从这里开始执行 5) 变量声明,在这个函数将要使用的变量 6) 计算机指令,各种语句,表达式,以及调用别的函数。 7) 一个 } 标志函数代码部分到次结束。除非这个函数的类型说明成 void,在 } 之前必须有个 return 返回和这个函数的数据类型,在 return 后继续执行调用这个函数的那个函数。 举个平凡的例子: ----- int my_function( string target ) { string name; object ppl name = "Trill"; if ( ppl = find_player( target ) ) { tell_object( ppl, "hi. My name is " + name + ". \n" ) return 1; } else { tell_object( this_player(), "sorry, i don't find the target : " + name + ".\n" ); return 0; } return 0; } ----- 这个函数接收一个 string 类型的参数,执行一些指令,返回一个 int 型的整数。 第三节 小结 定义了Lpc的Object的文件实际是由一些函数组成的。所有的函数,按 顺序由以下部分组成: 1) 函数声明 2) 函数定义(函数体) 3) 函数调用 3) The call 函数声明通常出现在这个文件的开头,在任何一个函数定义之前。必 须做到是,每个函数的被调用之前有函数的声明。在 XO 中规定严格一 些所有的函数必须有声明。 函数定义可以出现在文件的任何地方,只要在它的声明之后就可以了。 有一点要注意,不要在一个函数内部定义另一个函数。在 XO 中规定是 函数的定义按照一个给定的次序。 函数调用通常在别的函数定义的内部,如果你想要你的代码执行你写 的函数的话。当然也可以出现这个函数自己的函数定义内部,但是对于 一个新的巫师来说,最好别这么做,因为这样可能导致无限的循环。 每个 Driver 有自己一套 efun ,这些函数 Driver 已经替你声明过了, 也已经定义好了。efun 通常执行起来要比你自己写的函数快一些。更进 一步说,每个 MudLib 有一些特殊的函数看起来非常象 efun,他们也已 经声明过了,定义好了。他们被叫做 simul_efun,或者 sefun,或者叫 做 模拟 efun。对于 efun 的帮助,通常在 /doc/efun,或者 /help/wizard/efun,等类型的目录底下。很多 Mud 会提供一个指令,比 如 "man" 或 "help" 来提供在线帮助。 注意: 有些 Driver 对函数的类型检查不严格,甚至忽略你对函数那些特殊 的声明,比如 private 等等。但是不要管这个,你应该这样一个良好的 习惯,对函数的类型有严格声明。为什么? 1)对别的人(包括以后你自己)能更容易读你的程序,更快理解你这 部分代码想描述什么。这个对调试程序也是很有用的,大部分的 程序错误(包括 () 和 {} 的丢失)通常是数据类型不匹配。 2)因为这个被认为是个好的编程习惯。