PHP4手册:语法(五) 函式与物件
--------------------------------------------------------------------------------
函式
--------------------------------------------------------------------------------
在 PHP 中,允许程式设计者将常用的流程或者变数等元件,组织成一个固定的格式。也就是说使用者可以自行组合函式或者是物件。
PHP 中的函式 (function) 和 C 语言一样,包括有传回值的及无传回值的,不像 Pascal 分成函式 (function) 和程序 (procedure) 那么复杂。
在函式的名称上,PHP 对于大小写的管制很松散。可以在定义函式时写成大写的名字,而在使用时使用小写的名字。总之,对函式而言,不用管大小写,只要注意名称没有重复就好了。
以下就是函式的使用语法
function myfunc($arg_1, $arg_2, ..., $arg_n) {
// 执行一些动作
return $retval;
}
在使用时,在自定的函式名称前要加入 function 的保留字,表示这是定义使用者自定函式。之后的 myfunc 可以是任何的英文字母开头的字串,字串除了开头不能是数字或是底线,在第一个字母后可以是阿拉伯数字或者是底线,当然其它的符号或是中文字不能当函式名。
$arg_1 到 $arg_n 为函式使用的参数,参数之间使用逗号隔开。在参数后的大括号 {},即为整个函式的区段。函式若有传回值,使用 return 可将值传回。而参数可以事先定义初始值或内定值。有定义内定值的参数在使用函式时可以省略,但一定要放在没有设定内定值参数的后面,否则 PHP 在解析函式时,会出现错误。
另外就是参数的形态,只要参数是 PHP 支援的变数型态都可以使用,无论是阵列、字串、或是整数....等等。传回值也是一样。
下面即为使用内定值及不用内定值的例子
function myfunc1($arg_1, $arg_2, $arg_3="我是内定字串") {
echo $arg_1+$arg_2;
echo $arg_3."
\n";
}
myfunc(3, 4); // 参数 $arg_3 省略。
myfunc(6, 6, "不用内定值") // 输入参数 $arg_3。
?>
参数的值,通常使用传值的方式输入,有时在特别的需求时,可以使用传址的方式,传入参数的指标。方法就是在参数的前面加上 & 符号即可。如下例
function myfunc2(&$argstr) {
$argstr=ereg_replace("/", "-", $argstr);
}
$today="2000/01/01";
myfunc2($today);
echo $today; // 2000-01-01;
?>
--------------------------------------------------------------------------------
物件
--------------------------------------------------------------------------------
使用者定义的物件,也是学好 PHP 所必备的条件之一。而 PHP 的物件,和其它的物件导向语言比较起来,还算蛮单纯的。PHP 只有类别 (class)、方法 (method)、属性、以及单一继承 (extensions) 等。对不习惯使用 C++、Java、Delphi 等物件导向语言来开发程式的使用者,不妨先阅读一下有关物件导向观念的书,相信可以带来许多的收获。
下面的范例是手推车的物件。可以看到,使用 class 表示它是一个物件类别。在类别中的 function,例如 add_item 则表示该物件的一个方法。方法可以封装物件的实际处理情形,让该物件自己能依封装好的方法来执行一些动作。
程式中的 $this 物件变数也和 $GLOBALS 及 $php_errormsg 二个变数一样,在 PHP 中属于特殊的变数。$this 变数只用在物件类别中,表示物件的本身。
// 程式名: cart.inc
class Cart {
var $items; // 手推车物件
// 本方法加入 $num 件物品到手推车中 (加到 $artnr 变数)
function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}
// 本方法从手推车减少 $num 件物品 (从 $artnr 变数减掉)
function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}
?>
要使用手推车可以用类似下例的方式。可以先将每个物件存成 Include 档案,再将它 require 或 include 进来。在宣告变数 $cart 时,要使用 new 的保留字,表示 $cart 使用 Cart 物件。使用 -> 符号,表示执行物件的方法。
require("cart.inc");
$cart = new Cart;
$cart->add_item("10", 1);
?>
之后再设计有记名的手推车。记名手推车从手推车遗传下来,因此手推车拥有的方法及属性,记名手推车也有,而记名手推车比手推车增加了名字的方法 (或许该称属性较恰当)。
从下例中可以看到,子物件 Named_Cart 使用 extends 来继承其父物件 Cart。虽然 Named_Cart 物件中没有增加物品及减少物品的方法,不过由于遗传的特性,父物件有的东西它都有。
// 程式名: named_cart.inc
require("cart.inc");
class Named_Cart extends Cart {
var $owner;
function set_owner ($name) {
$this->owner = $name;
}
}
?>
要使用记名手推车物件,请看下面的范例。当然这不算太好的设计,每个子物件都一直 require 它的父物件,会造成伺服器在 I/O 上面的负担。在实作时,可以将整个系列的物件在同一个程式档案中,从最早的?先物件到最后的子孙物件,也方便日后修正。
require("named_cart.inc");
$ncart = new Named_Cart; // 建立物件变数
$ncart->set_owner ("CyberRidder"); // 设定物件的记名属性
echo $ncart->owner; // 显示物件的记名属性
$ncart->add_item ("10", 1); // 从父物件遗传的方法也可使用
?>
因此,在 PHP 中使用了 extends 保留字,加上良好的系统分析与完整的 CRC 卡片 (详见物件导向相关书籍) 设计之后,PHP 可变成拥有强大物件能力的 CGI 语言。
PHP 由于是剧本语言 (Script),因此程式原始码可见,在软体工程中的元件黑箱并不会在目前的 PHP 版本中出现,也就是说,全部的物件其实没有隐藏起它的内容。对于软体业者而言,没有办法保护所谓的软体 IC,站在开放社群而言,反而有原始码是件好事,至于孰是孰非,就很难判定了,不过目前 PHP 还是 Open Source 社群的一份子,或许日后 Zend 引擎可以做到物件封装的功能也不一定。