search
Homephp教程php手册为面向对象而生的PHP5

php5|对象

摘要]目前开发中的PHP5,其面向对象的机能已经被大幅度的强化了。下一代的PHP将会是怎样的一种语言呢?下面我们来详细讲解一下目前发布的PHP5的beta release。




(一) Zend 2.0的诞生
现在的PHP4所使用的基本文法是被称之为Zend 引擎的脚本编译引擎。这个就是PHP4的优良机能的原因之一,是作为对PHP3的改进而生成的一种语言。大家一直认为,PHP4的性能根据当初的目标,比PHP3有了很大的提升,在网络编程的世界里占据了很大的份额。

开发了Zend 引擎的Zend公司是在开发PHP4的同时,由PHP3的主要开发者Zeev Suraski和Andi Gutmans所创立的企业合并而来的。Zend的名称是由Zeev和Andi的名字合起来组成的。Zend公司的商业模式是,持续不断的为open source提供zend 引擎的PHP内核 (core),同时提升周边产品开发和贩卖的利益。以open source software作为基盘的商业,在世界范围内大多数正在苦战的企业中,算是比较好的典型例子了。

■PHP4的局限

托PHP4成功的福,这个用途的适用范围逐渐变广起来。作为企业级的用途而使用PHP的说法时有所闻。因此,就有了这样一个问题,构筑大规模网站的时候,代码的再利用性十分差。具体来说就是,PHP4的面向对象性能很弱,因此习惯于使用Java等的技术人员对此有很多的抱怨。

逐步的改善PHP4的面向对象的性能,大幅度的更改基本文法,开发者达成了更新PHP记述方法的开拓目的。

■Zend 2.0开始开发
随后,Zend公司PHP中心的开发者们在2001年7月发表了作为下一代PHP语言引擎的Zend 2.0引擎的构想。以[Zend Engine version 2.0: Feature Overview and Design]
(http://www.zend.com/engine2/ZendEngine-2.0.pdf)作为目标的同时,面向对象的性能大幅度的强化了。
目前的PHP4 Zend 引擎的扩张情况与昔日的PHP3如出一辙。这就意味着,要提升新的语言引擎的主版本号,明确方法目标,迎接来自开发团体的称赞。

Ze2的开发,与以往的Zend引擎一样,都是运行在open source的模式下的。最新的源代码在CVS上被全面的公开,因为是面向开放的开发者的,关于开发的议论非常的活跃。

现在Ze2被决定采用于PHP的下一个版本PHP5中。最终发布的时间现在还未定,但是假如根据Zend公司2003年4月1日发布的Newsletter的话,现在的应该就是Beta Release了。


(二) PHP5的新特性

接下来请按照顺序看一下被强化的PHP5的性能。首先是最为重要的面向对象性能,类的实体特性在大幅度的被修改着。这里说的仅是关于类的新特性。

· 对象的参照过渡是默认的(default)
· 引入访问属性的限制
· 引入访问方法的限制
· 抽象类和抽象方法
· 接口
· final声明
· 名空间
· 类内常量
· 类变量
· 统一构建器
· 析构函数(Distructor)
· 其他附属特性

以上内容是根据2003年4月22日CVS上登录版本资料所写的,在正式的发布之前,也有变动的可能性。

■对象的默认参照过渡

在PHP4中,在以变量$var1为类的实体对象的时候,如果$var2 = $var1;那么,在$var2中,$var1的复制被代入。明显的,$var2为了指向与$var1相同的对象,就要写成$var2 =& $var1,必须要加上&作为参照。
而在PHP5,对象的代入将成为自动的参照过渡。也就是说,
$var2=$var1,两者指向相同的对象。如果想要同php4一样,带入copy,那么就会运用到导入__clone()的方法。
$var2 = $var1->__clone();此处,clone前面是两个连续的“_”
(这仅仅是类的实体的特性)


■引入访问属性的限制

在PHP4的类中,连同属性和方法在内,可以自由的访问类的内外任何地方,而没有限制。因此,用户就无法防范属性的无意中的更改。

而在PHP5中,同C++和Java一样,导入了private, protected, public三个等级的访问限制,使得类的设计者能够对属性和方法的使用方法进行限定。以下是各种访问限制的意思。

· Public: 可以自由的在类的内外任何地方进行参照、变更
· Private: 只能在这个类的方法中进行参照、变更
· Protected:能够在这个类以及继承了这个类的另一个类的方法中进行参照、变更。另外,在继承的类中,能够写入访问指定。

在PHP4中的“var”,同以往一样与public有着相同的意思。下面就来举一个例子,让我们来看看访问限制是怎样起作用的。

PHP代码:--------------------------------------------------------------------------------
class Hoge1 {
 private $var1 = 'A';
 protected $var2 = 'B';
 protected $var3 = 'C';

 function setLower() {
  $this->var1 = 'a';
  $this->var2 = 'b';
  $this->var3 = 'c';
 }
 function var1() {
  return $this->var1;
 }
 function var2() {
  return $this->var2;
 }
 function var3() {
  return $this->var3;
 }
}

--------------------------------------------------------------------------------

在这个类中,带有$var1, $var2, $var3三个属性。$var1被声明为private, $var2和$var3是protected.在此处

PHP代码:--------------------------------------------------------------------------------
$hoge=new Hoge1;
echo’var1:’.$hoge->var1.”
n”

--------------------------------------------------------------------------------

如果尝试参照不允许从外部进行访问的private属性,那么就会出现如下错误:

Fatal error: Cannot access private property hoge1::$var1 in /path/to/script.php on line XX

对于protected的$var2也是相同的。

但是,因为$hoge的方法是没有private和protected的,所以下面的代码能够正常运作,返回内部私有和保护变量的值。

PHP代码:--------------------------------------------------------------------------------
echo 'var1: ' . $hoge->var1() . "
\n"; // var1: A
echo 'var2: ' . $hoge->var2() . "
\n"; // var2: B
echo 'var3: ' . $hoge->var3() . "
\n"; // var3: C

$hoge->setLower();

echo 'var1: ' . $hoge->var1() . "
\n"; // var1: a
echo 'var2: ' . $hoge->var2() . "
\n"; // var2: b
echo 'var3: ' . $hoge->var3() . "
\n"; // var3: c

--------------------------------------------------------------------------------

其次,为了能够看到protected的属性的状态,我们试着创造了继承了Hoge1的类Hoge2

PHP代码:--------------------------------------------------------------------------------
class Hoge2 extends Hoge1 {
 public $var3 = '3';

 function d_var1() {
  return $this->var1;
 }
 function d_var2() {
  return $this->var2;
 }
 function d_var3() {
  return $this->var3;
 }
}

--------------------------------------------------------------------------------

在类Hoge2中,只有$var3被声明为public。在属性是protected的情况下,从子类进行访问有何种限制,是由子类的属性声明决定的。在Hoge2中,因为$var3被声明是public,因此无论是从何处都可以访问Hoge2的$var3(实体是Hoge1的$var3)。因为$var1在Hoge1中是private,因此,在Hoge2子类中Hoge1的$var1不会被继承,而在Hoge2中有可能会做出名为$var1的属性,因此,必须要明确区分Hoge1::$var1和Hoge2::$var1。

PHP代码:--------------------------------------------------------------------------------
$hoge = new Hoge2;

echo 'var1: ' . $hoge->var1 . "
\n";   // var1:
// echo 'var2: ' . $hoge->var2 . "
\n";  // Error
echo 'var3: ' . $hoge->var3 . "
\n";   // var3: 3

echo 'var1: ' . $hoge->d_var1() . "
\n"; // var1:
echo 'var2: ' . $hoge->d_var2() . "
\n"; // var2: B
echo 'var3: ' . $hoge->d_var3() . "
\n"; // var3: 3

--------------------------------------------------------------------------------


$hoge->var1是与Hoge1::var1没有关系的变量,因此不会有任何显示,因为var2有protected访问限制,所以如果不通过method就直接参照$var2,就会出现致命错误。

■引入访问方法的限制

与上述相同,此处也分为private, protected, public三种。

· Public: 能够从任何地方调用
· Private: 只能够从这个类的method内调用
· Protected: 只能够从这个类以及subclass的method中调用

此处的意思同Java和C++相同,请不要搞混。

■抽象(abstract)的类和抽象的方法

支持与Java相同的抽象类和抽象方法。抽象方法只提供了方法名的调用方式,而没有提供实体。另外,持有抽象方法的类,必须抽象宣言类本身。如果想要直接作成抽象类的对象,那么就会出现如下的致命错误。

Fatal error: Cannot instantiate abstract class ClassName

产生错误的实际的例子如下所示:

PHP代码:--------------------------------------------------------------------------------



abstract class MyAbstract {
 abstract public function test();
 public function test2() {
  echo "MyAbstract::test2() called.
\n";
 }
}

class MyImplement extends MyAbstract {
 public function test() {
  echo "MyImplement::test() called.
\n";
 }
}

$obj = new MyImplement;
$obj->test();

?>

--------------------------------------------------------------------------------


■接口(interface)

支持与Java相同的接口(interface)。接口是适合所描述的外部调用形式而设计组合起来的。
接口的实体不能够记录。相反的,实现接口的类必须持有与这个接口的方法相对应的实体。另外,类能够实现多个接口,因此,有可能实现多重继承。

PHP代码:--------------------------------------------------------------------------------


interface Throwable {
 public function getMessage();
}

interface Serializable {
 public function toString();
}

class MyException implements Throwable, Serializable {
 public function getMessage() {
  return 'this is MyException message';
 }

 public function toString() {
  return 'MyException: this is MyException message';
 }
}

$e = new MyException;
echo $e->getMessage();
echo $e->toString();
?>

--------------------------------------------------------------------------------


■final声明

同Java一样,PHP5支持final声明。如果对于一个方法追加final声明,这个方法将肯定在子类不能重载(Override)。如果方法被final声明了,但是还在子类中重载,就会出现如下错误:

PHP代码:--------------------------------------------------------------------------------
Fatal error: Cannot override final method fuga::foo()

--------------------------------------------------------------------------------


产生错误的例子:

PHP代码:--------------------------------------------------------------------------------

class Fuga {
 final function foo() {
  echo "this is final function\n";
 }
}

class Hoge extends Fuga {
 function foo() {
  echo "this is not final function\n";
 }
}
?>

--------------------------------------------------------------------------------


(三) PHP5的新特性(续)

PHP5的发布计划

在前面的文章中我们提到,“根据ZEND公司2003年4月1日发布的讯息的话,现在的应该就是Beta Release了”,但是开发者内部讨论的结果是,Beta为时尚早,而且有可能不是Beta Release.

对这方面动向有兴趣的可以参照 news://news.php.net/ 上所公布的信息 php.version5.dev:372

在这个文件中,PHP5的发布计划又重新回到了一张白纸,而另一方面,Zend Engine2的开发正在着手进行中。PHP5的Release其实大体就是盼望着“快点到年终吧”。

PHP5的新特性

接着我们来看一下在前面所讲到的其他一些关于类的新增的机能

■名空间

PHP5支持名空间。因此,我们可以在名空间内装入类、变量、常量、函数。

在PHP4的Scope中,只有global、函数内、类内这三个种类,所以要特别注意如果不注意的话,将会很容易“污染”global空间。假如使用名空间的话我们就能够在package里分离变量命名空间,因此应该就能比较容易的做成独立的package。

使用实例如下:

PHP代码:--------------------------------------------------------------------------------
namespace This {
 class Hoge {
 }
 const aConstant = 'This Constant';
 function aFunction() {}
 var $aVariable = 'This Variable';
}

$obj = new This::Hoge;
echo This::aConstant . "
\n";
This::aFunction();
echo This::$aVariable . "
\n";

--------------------------------------------------------------------------------


假设要访问名空间内的对象的话,就应该这样做:

名空间名::对象名

但是PHP5的名空间不会套入与C++相异的样子。

■Class内常量

使用关键字const,能够在类、名空间内定义常量。这里因为是常量,因此一定要在常量名的前面加上$。Class内的常量,比这个类中的global常量的优先级要高。

在这里const是预约语,因此在class名和函数名中使用const的时候要做必要的修正。

PHP代码:--------------------------------------------------------------------------------


define('constant_value', 'global constant');

class MyClass {
 const constant_value = 'class constant';

 function printConstant() {
  print constant_value;
 }
}

echo MyClass::constant_value . "
\n";
MyClass:rintConstant();
?>

--------------------------------------------------------------------------------


在这个例子里,MyClass:rintConstant()是显示常量constant_value的值,但是,constant_value存在于global空间和Class内这两个地方。在这种情况下,MyClass内的常量constant_value的优先级较高,被显示为「class constant」。

■对象变量

即使是在类没有被实例化状态下,对象变量也能准确的按照指定的值被初始化。访问的方法如下:

类名::$变量名

PHP代码:--------------------------------------------------------------------------------


class Hoge {
 static $my_static = 5;
}

print Hoge::$my_static;
?>

--------------------------------------------------------------------------------


■统一构建器

在生成对象的时候,能够自动被调用的方法被称作“构建器”。

PHP4中的构建器,是与Class名相同的方法名。这是与Java和C++相同的地方,因此,对于一些用惯了的人来说,不会有别扭感。但是,如果要从子类中调用父类的构建器的话,在PHP中就必须特意写上父类的名字。

在PHP中,父类的构建器不能被自动调用,因此,情况就比较多。
在PHP5中,统一采用了__constructor这个构建器名称,不管class名是什么,凡是被称为__construct()的,都被当作构建器来处理。

另外,考虑到同PHP4的互换性,假如存在于Class名相同的以前的构建器名,那么,优先使用那个构建器。

PHP代码:--------------------------------------------------------------------------------


class BaseClass {
 function __construct() {
  print "In BaseClass constructor\n";
 }
}

class SubClass extends BaseClass {
 function __construct() {
  parent::__construct();
  print "In SubClass constructor\n";
 }
}

$obj = new BaseClass();
$obj = new SubClass();
?>

--------------------------------------------------------------------------------


■析构函数

与构建器相反,能够在对象释放时自动被调用的方法被称为析构函数。

PHP4支持析构函数,通过登录在PHP运行终止时用register_shutdown_function()调用的函数,只有类似的实行方法。PHP5正式支持析构函数,能够在类中指定对象释放时的动作。

析构函数就是名为__destruct的方法。当对象内部的参照计数器变成0的时候,__destruct()被调用,然后对象所使用的内存被释放出来。

PHP代码:--------------------------------------------------------------------------------


class MyDestructableClass {
 function __construct() {
  print "In constructor\n";
  $this->name = 'MyDestructableClass';
 }

 function __destruct() {
  print 'Destroying ' . $this->name . "\n";
 }
}

$obj = new MyDestructableClass();
?>

--------------------------------------------------------------------------------


另外,与构建器相同的地方是,父类的析构函数不能被自动的调用,必要的时候,需要用命令:

parent::__destruct();

■访问

在PHP4中,如果访问了一个不存在的属性,那么系统就会自动生成与之相对应的新属性。

PHP代码:--------------------------------------------------------------------------------
class Hoge {
}

$obj = new Hoge;
$obj->prop = "This is new property";

--------------------------------------------------------------------------------



如上所示,当把值代入一个不存在的属性时,那个代入点就会自动生成一个新属性。同样的,访问一个不存在的属性,就如同被代入NULL值的变量一样,不会发生错误。

在PHP5中追加了一点,就是能够对访问任意的属性进行控制。在类中如果存在__set()、__get()这样的方法,替代上述的动作此处的方法将能够被调用。例如:

PHP代码:--------------------------------------------------------------------------------


class Hoge {
 function __set($name, $value) {
  print "__set() is called with ($name, $value)\n";
  $this->$name = $value;
 }
}

$obj = new Hoge;

$obj->a = '123';
$obj->a = '456';
$obj->b = '789';
?>

--------------------------------------------------------------------------------


在这里,__set 方法被作为未定义属性的代入方法,在显示值之后将值代入未定义属性。

PHP代码:--------------------------------------------------------------------------------
$obj->a = '123';

--------------------------------------------------------------------------------


执行这一句时,因为在这个时候不存在属性a,因此,作为代替,__set 方法被调用。

__set() is called with (a, 123)

其次,

$obj->a = '456';

再一次的代入$obj->a,这一次,由于属性a已经存在,所以__set 没有被调用,和通常一样把值代入到了属性a中去了。

$obj->b = '789';

这一回,我们把值代入另一个属性b中,同a的第一次情况一样,

__set() is called with (b, 789)

同__set 方法相反,__get 方法是在对不存在的属性的引用时调用的。将这两者结合起来,再来看一下对于属性的访问,实际上,利用它能够写出在不同的场合都能做出不同响应的类来。

PHP代码:--------------------------------------------------------------------------------


class Hoge {
 public $properties;

 function __set($name, $value) {
  $this->properties[$name] = $value;
 }
 function __get($name) {
  return $this->properties[$name];
 }
}

$obj = new Hoge;

$obj->a = '123';
$obj->b = '456';
echo $obj->a;
echo $obj->b;

print_r($obj);
?>

--------------------------------------------------------------------------------


在这个例子里,对类中所有属性的访问被装入了$properties中,这样,使我们加入的属性不直接的附在对象之下。这是个不太能容易理解的例子,例如,试着把这个例子中的保存到$properties改成存入文件或是数据库会很有趣吧。实际上,在对象里面,我们能够简单的实现让许多的复杂的操作。

与__set, __get多少有些不同,但是__call也能用来书写不存在的方法,当我们向如下例子一样调用对象的方法的时候,

$object->methodname();

如果这个类中不存在methodname这个方法,通常情况下,就会出现如下错误:

Fatal error: Call to undefined method Class::methodname()

但是,如果这个类中存在__call这个方法,作为替代,__call就被调用。__call的参数有两个,第一个参数是被叫出的方法名,第二个参数是保持了的被调用的参数的数组。考虑到有很多的使用方法,除了以下的例子外,还可以使用其它的方法。

PHP代码:--------------------------------------------------------------------------------


class Proxy {
 private $object;

 function __call($name, $params) {
  if (isset($this->object)) {
   if (method_exists($this->object, $name)) {
   return call_user_func_array(array($this->object, $name), $params);
   }
   else {
   return "method not exists.";
   }
  }
 }
 function __construct($object) {
  $this->object = $object;
 }
}

class Hoge {
 function add($var1, $var2) {
  return $var1 + $var2;
 }
}

$p = new Proxy(new Hoge);

$result = $p->add(1, 2);
echo "result: $result
\n";

$result = $p->sub(5, 3);
echo "result: $result
\n";
?>



Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python中的class类和method方法的使用方法Python中的class类和method方法的使用方法Apr 21, 2023 pm 02:28 PM

类和方法的概念和实例类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。类的构造方法__init__():类有一个名为init()的特殊方法(构造方法),该方法在类实例化时会自动调用。实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self修饰的变量。实例化:创建一个类的实例,类的具体对象。继承:即一个派生类(derivedclass)继承基类(baseclass)的

function是什么意思function是什么意思Aug 04, 2023 am 10:33 AM

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果,其目的是封装一段可重复使用的代码,提高代码的可重用性和可维护性。

python中class是什么意思python中class是什么意思May 21, 2019 pm 05:10 PM

class是python中的一个关键字,用来定义一个类,定义类的方法:class后面加一个空格然后加类名;类名规则:首字母大写,如果多个单词用驼峰命名法,如【class Dog()】。

SpringBoot怎么通过自定义classloader加密保护class文件SpringBoot怎么通过自定义classloader加密保护class文件May 11, 2023 pm 09:07 PM

背景最近针对公司框架进行关键业务代码进行加密处理,防止通过jd-gui等反编译工具能够轻松还原工程代码,相关混淆方案配置使用比较复杂且针对springboot项目问题较多,所以针对class文件加密再通过自定义的classloder进行解密加载,此方案并不是绝对安全,只是加大反编译的困难程度,防君子不防小人,整体加密保护流程图如下图所示maven插件加密使用自定义maven插件对编译后指定的class文件进行加密,加密后的class文件拷贝到指定路径,这里是保存到resource/corecla

"enumerate()"函数在Python中的用途是什么?"enumerate()"函数在Python中的用途是什么?Sep 01, 2023 am 11:29 AM

在本文中,我们将了解enumerate()函数以及Python中“enumerate()”函数的用途。什么是enumerate()函数?Python的enumerate()函数接受数据集合作为参数并返回一个枚举对象。枚举对象以键值对的形式返回。key是每个item对应的索引,value是items。语法enumerate(iterable,start)参数iterable-传入的数据集合可以作为枚举对象返回,称为iterablestart-顾名思义,枚举对象的起始索引由start定义。如果我们忽

php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决Jun 13, 2016 am 10:23 AM

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code<form name="myform"

MySQL.proc表的作用和功能详解MySQL.proc表的作用和功能详解Mar 16, 2024 am 09:03 AM

MySQL.proc表的作用和功能详解MySQL是一种流行的关系型数据库管理系统,开发者在使用MySQL时常常会涉及到存储过程(StoredProcedure)的创建和管理。而MySQL.proc表则是一个非常重要的系统表,它存储了数据库中所有的存储过程的相关信息,包括存储过程的名称、定义、参数等。在本文中,我们将详细解释MySQL.proc表的作用和功能

在 Windows 11 上修复音频服务无响应问题的 18 种方法在 Windows 11 上修复音频服务无响应问题的 18 种方法Jun 05, 2023 pm 10:23 PM

音频输出和输入需要特定的驱动程序和服务才能在Windows11上按预期工作。这些有时最终会在后台遇到错误,从而导致音频问题,如无音频输出、缺少音频设备、音频失真等。如何修复在Windows11上没有响应的音频服务我们建议您从下面提到的修复开始,并逐步完成列表,直到您设法解决您的问题。由于Windows11上的多种原因,音频服务可能无法响应。此列表将帮助您验证和修复阻止音频服务在Windows11上响应的大多数问题。请按照以下相关部分帮助您完成该过程。方法一:重启音频服务您可能会遇

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Tools

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),