PHP5面向对象

    PHP从PHP3开始采用面向对象。在PHP5版本,随着向Zend2引擎转移,对功能进行了大幅度的改善。
采用面向对象开发程序,可以提高程序代码的安全性和可再使用性。从使用PHP5开始尝试引入面向对象
开发/设计怎么样?这篇文章将主要说明与面向对象相关的主要变化。


1 开始
    用PHP开发时,以页面为中心编写代码时,总是容易将处理过程写的冗长繁琐。程序的规模稍微大一
点的话,立刻会因安全性方面的困难而令人苦恼。比如说在B页面和A页面进行同样的处理,因为不能把处
理编写成可以重复使用的形式,所以不得不进行拷贝粘贴等工作。这种情况增多的话,一旦拷贝的代码被
改变,需要改动的地方就增多,漏改的可能性也增大。
    采用面向对象开发程序的话,就会编出安全性较高的代码。PHP从PHP3开始采用面向对象。在PHP4进行
了一些扩展,到了PHP5则完全重写。这些改进,引入了很多Java和C++中的优良功能,使PHP的面向对象开
发更加正规。这篇文章将主要说明PHP5(Zend Engine 2)在面向对象方面新追加的功能。
    让我们以此为契机,尝试一下面相对性开发吧。
2 新功能一览
    Zend公布的正式文件中列出的新功能。
   
    支持Private和Protected
    抽象方法和抽象类
    接口
    final关键字
    Object的复制
    新构造函数
    destructor(处理无用的对象)?
    常数
    例外处理
    方法的返回值因对象的不同而不同
    静态方法
    instanceof 运算符
    静态方法的变量操作
    当方法的参数是reference时可以为参数设默认值?
    类定义的自动读入
    访问方法和属性时的操作可以被替换?

    下面对他们进行详细介绍。

3 支持private,protected成员
    可以将类的属性和方法定义为private或protected。

    private 只能从该类内访问的成员
    protected 只能从该类和该类的父类内访问的成员
    public 从任何类和PHP文件都能访问的成员。

<?
// ------------------------------------------------------------------
class ParentClass {
  private     $secret = "private变量";
  protected $domestic = "protected变量";

  function test() {
    print "1 : " . $this->secret . "/n";
    print "2 : " . $this->domestic . "/n";
  }
}
// ------------------------------------------------------------------
class ChildClass extends ParentClass {
  function test2() {
    // print "3 : " . $this->secret . "/n";      // 不能访问
    print "4 : " . $this->domestic . "/n";
  }
}
// ------------------------------------------------------------------
$p = new ParentClass();
$c = new ChildClass();

$p->test();

$c->test();
$c->test2();

// print "5 : " . $p->secret . "/n";    // 不能访问
// print "6 : " . $p->domestic . "/n";  // 不能访问
// print "7 : " . $c->secret . "/n";    // 不能访问
// print "8 : " . $c->domestic . "/n";  // 不能访问
// ------------------------------------------------------------------
?>

    运行结果

1 : private变量
2 : protected变量
1 : private变量
2 : protected变量
4 : protected变量

    如果违反了访问权限的话就会出现Fatal Error错误。

3 抽象方法和抽象类,接口
    在PHP中也可以使用抽象方法和抽象类,抽象类是因含有没有方法体的方法而不能实例化的类。没有方
法体的方法是抽象方法。
    定义抽象类时使用abstract修饰符

<?
abstract class AbstractClass {
  abstract public function test();
}

class Impl1 extends AbstractClass {
  public function test() {
    print "this is a test by Impl1./n";
  }
}

class Impl2 extends AbstractClass {
  public function test() {
    print "this is a test by Impl2./n";
  }

  // 可以追加新的方法
  public function hoge() {
    print "hogehoge;/n";
  }
}

// $a = new AbstractClass(); // 抽象类不能实例化

$i1 = new Impl1();
$i1->test();

$i2 = new Impl2();
$i2->test();
?>

    运行结果

this is a test by Impl1.
this is a test by Impl2.

    如上,在抽象方法中无方法体。还有,抽象类不能实例化。如果想实例化,需要开发该抽象类的子类,
此时,子类必须写出抽象类中抽象方法的方法体。(如例中的test方法)
    另外,当类中的方法全部为抽象方法时,可以使用接口。

<?
interface MyInterface {
  public function test();
}

class Impl implements MyInterface {
  public function test() {
    print "hogehoge/n";
  }
}

$i = new Impl();
$i->test();
?>

    运行结果

hogehoge

    为实现接口要用到关键字implements。定义借口时,里面的方法可以省略关键字abstract。

5 自动读入类
    对未定义的类进行实例化时,需要追加将类自动调出的方法。添加需要用到的类时,全部使用include
调用的话浪费资源,有选择性的调用的话又有些麻烦,此时使用此功能。
    将__autoload()方法定义为全局函数,通过该方法可将未用include调用的类实例化。参数为类名。

function __autoload($className) {
  include_once $className . ".php";
}

    只需通过对以上全局函数(不是方法)的定义,include定义就变得毫无必要(此例是在类名与文件名
相对应的情况下)。实际上上述函数定义最好在所有的页面进行。

    *类名中含有大写字母的话,必须转成小写字母。因此上例的类的文件名必须全部用小写字母。

6
    定义__set(),__get()方法后,对所有的属性进行访问时处理将发生变化。定义__set()方法后,更新
属性值时,将调用__set()方法。定义__get()方法后,提取属性值时,将调用__get()方法。
    __get()方法的参数是属性名,__set()方法的参数是属性名和更新的值。

<?
class PropertyOverload {
  public $valList = Array();

  function __get($valName) {
    print ":: Getter called ($valName)./n";
    if( isset($this->valList[$valName]) ) {
      // 返回值是原值的1.25倍
      return $this->valList[$valName] * 1.25;
    } else {
      return null;
    }
  }

  function __set($valName, $newValue) {
    print ":: Setter called ($valName, $newValue)./n";
    $this->valList[$valName] = $newValue;
  }

  function showStatus() {
    print_r( $this->valList );
  }
}

$obj = new PropertyOverload();

print "---------------------------------------/n";
$obj->val1 = 100;
print "---------------------------------------/n";
$obj->val2 = 150;
print "---------------------------------------/n";
print $obj->val1 . "/n";  // 调用__get(),返回值是原值的1.25倍
print "---------------------------------------/n";
$obj->showStatus();

?>

    运行结果

---------------------------------------
:: Setter called (val1, 100).
---------------------------------------
:: Setter called (val2, 150).
---------------------------------------
:: Getter called (val1).
125
---------------------------------------
Array
(
    [val1] => 100
    [val2] => 150
)

    *只有对没有被作为成员登录的变量(改变量没有被明确定义)访问时,才调用__get(),__set()方法
。不知是有意为之,还是错误。
    还有,定义__call()后,调用一个类中未定义的方法时,调用__call()方法。__call()方法的参数是
被调用的方法名和参数数组。

<?
class MethodOverload {
  function __call($methodName, $argsArray ) {

    print ":: /"$methodName/" Method was called./n";

    switch($methodName) {
    case "nomethod":
      // 将参数数组中的值指定到已定义的方法的参数中?
      call_user_func_array( Array( &$this, "hoge"), $argsArray );
      break;
    }

  }

  function hoge($p1, $p2, $p3) {
    print "this is test method. Params are ($p1, $p2, $p3)./n";
  }
}

$obj = new MethodOverload();
$obj->nomethod(2, 4, 8);

// 调用已定义的方法时,不调用__call()方法
print "----------------------------------------------/n";
$obj->hoge(1, 2, 3);

    运行结果

:: "nomethod" Method was called.
this is test method. Params are (2, 4, 8).
----------------------------------------------
this is test method. Params are (1, 2, 3).

?>

使用__set(), __get(), __call()会导致程序安全性降低,一般不鼓励使用。

7 总结
    private和protected的引入使对象的信息隐藏成为可能。另外抽象类的实现使PHP可以在更加正规的面
向对象的开发中使用。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值