一、类的结构
限定符——public、protect、privite、final
public :默认选项,公有的属性或方法可以在类的内部和外部进行访问。
protect :该属性或方法只能在类内部进行访问。它也存在于任何子类。
private :该属性或方法只能在类内部进行访问。私有的属性和方法将不会被子类继承。
final :当在一个函数声明前面使用这个关键字时,这个函数将不能 在任何子类中被重载。也可以在类前面使用该声明,则该类无法被继承
结构与实例化
构造函数 __construct($param)
:当创建一个对象时,它将调用构造函 数,通常,这将执行一些初始化任务(例如,设置属性的初始值)。 注意 构造函数的名称不可自定义,必须为“__construct”。
在示例中,执行154,155行代码,将显示:
析构函数 __destruct()
: 与构造函数相对的就是析构函数。析构函数允许在销毁一个类之前执行一些操作或完成一些功能。 注意 析构函数的名称不可自定义,必须为“__destruct()”。
使用类的属性—-指针this
当前类的一个属性为 $attribute
,则可以使用 $this->attribute
来引用在 当前这个类 中的这个属性。(如:161,162行的引用)。
在本例中,由于限定符为 public
,则也可以在外部访问该成员属性和方法(不鼓励这种访问方式):
推荐使用的访问方式——__get()和__set()函数
__get()
函数返回了 $attribute
的值;
__set()
函数设置了 $attribute
的值。
工作原理
例如:设置$a->attribute;
将间接调用__get()
函数,将$name
参数的值设置为”attribute”;
设置 $a->$attribute=5;
该语句将间接调用__set()
函数,将$name
参数的值设置为”attribute”,而$value
的值被设置为5。
好处
只有一个访问入口(__get()
和__set()
),就可以实现对要保存的数据进行检查,即当每次调用该数据时不用在外部对这个数据进行反复操作,而直接在这两个函数中设置对$name
和$value
的检查。
调用类的function
假设有一个类:
则使用其中的两个类操作,语法可以为:$a->operation1();
和$a->operation2(12,"test");
二、继承、重载
继承
语法:class B extends A{}
。
B是A的子类,B中类默认包含了A类中的public
和protect
定义的属性和方法,同时还可以在B类中自定义属于B类的属性和方法。
重载
假设有类A:
,如果需要改变$attribute
的默认值,并为operation()操作提供新的功能,可以创 建类B,它重载了$attribute
和operation()
方法,注意,这种方法不会影响A中的属性和方法:
三、接口
接口的使用,可以实现类的多重继承功能。
接口的定义
接口的继承
四、实例使用
(基于第五章的实例)
新建立一个page.inc 文件:
<?php
class Page
{
//class Page's attributes
public $content;
public $title="TLA Consulting Pty Ltd";
public $keywords="TLA Consulting,Three Letter Abbreviation, some of my best friends are search engines";
//使用一个数组,来保存按钮的文本标签 以及该按钮指向的URL:
public $buttons=array("Home"=>"home.php",
"Contact"=>"contact.php",
"Services"=>"services.php",
"Site Map"=>"map.php" );
//class Page's operations
//定义访问函数以设置和获得已定义的变量值
public function __set($name,$value){
$this->$name=$value;
}
//显示函数,主要功能是显示HTML页面
public function Display(){
echo"<html>\n<head>\n";
$this->DisplayTitle();
$this->DisplayKeywords();
$this->DisplayStyles();
echo"</head>\n<body>\n";
$this->DisplayHeader();
$this->DisplayMenu($this->buttons);
echo$this->content;
$this->DisplayFooter();
echo"</body>\n</html>\n";
}
public function DisplayTitle(){
echo"<title>".$this->title."</title>";
}
public function DisplayKeywords(){
echo"<meta name=\"keywords\" content=\"".$this->keywords."\"/>";
}
//函数DisplayStyles()、DisplayHeader()和DisplayFooter() 需要显示没有经过PHP处理的大量静态HTML。
//因此,简单地使用了PHP结束标记(? >)、输入HTML,然后再在函数体内部使用一个PHP打开标记(<?php)
public function DisplayStyles(){
?>
<style>
h1{
color:white;font-size:24pt;text-align:center;
font-family:arial,sans-serif
}
.menu{
color:white;font-size:12pt;text-align:center;
font-family:arial,sans-serif;font-weight:bold
}
td{
background:black
}
p{
color:black;font-size:12pt;text-align:justify;
font-family:arial,sans-serif
}
p.foot{
color:white;font-size:9pt;text-align:center;
font-family:arial,sans-serif;font-weight:bold
}
a:link,a:visited,a:active{
color:white
}
</style>
<?php
}
public function DisplayHeader(){
?>
<table width="100%"cellpadding="12"
cellspacing="0"border="0">
<tr bgcolor="black">
<td align="left"><img src="logo.gif"/></td>
<td>
<h1>TLA Consulting Pty Ltd</h1>
</td>
<td align="right"><img src="logo.gif"/></td>
</tr>
</table>
<?php
}
public function DisplayMenu($buttons){
echo"<table width=\"100%\"bgcolor=\"white\" cellpadding=\"4\"cellspacing=\"4\">\n";
echo"<tr>\n";
//calculate button size
$width=100/count($buttons);
while(list($name,$url)=each($buttons)){
$this->DisplayButton($width,$name,$url,
!$this->IsURLCurrentPage($url));
}
echo"</tr>\n"; echo"</table>\n";
}
//判断按钮URL是否指向当前页。
public function IsURLCurrentPage($url){
//字符串函数strpos(),它可以查看给定的URL是否包含在服务器设置的变量中。
//strpos($__SERVER['PHP_SELF'],$url)语句将返回:
//一个数字(如果$url中的字符串包含在全局变量$_SERVER['PHP_SELF'])
//或者false(如果没有包含在全局变量中)。
if(strpos($_SERVER['PHP_SELF'],$url)==false){
return false;
}
else{
return true;
}
}
//输出一个简单的菜单按钮。如果该按钮指向当前所在的页面,将显示一个没有激活的按钮,
//并且不指向任何页面。这可以使得整个页面布局和谐,并且访问者可看出自己的位置。
public function DisplayButton($width,$name,$url,$active=true){
if($active){
echo"<td width=\"".$width."%\"> <a href=\"".$url."\"> <img src=\"s-logo.gif\"alt=\"".$name."\"border=\"0\"/></a> <a href=\"".$url."\"><span class=\"menu\">".$name."</span></a> </td>";
}
else{
echo"<td width=\"".$width."%\"> <img src=\"side-logo.gif\"> <span class=\"menu\">".$name."</span> </td>";
}
}
public function DisplayFooter(){
?>
<table width="100%"bgcolor="black"cellpadding="12"border="0">
<tr>
<td>
<p class="foot">&copy;TLA Consulting Pty Ltd.</p>
<p class="foot">Please see our<a href="">legal
information page</a></p>
</td>
</tr>
</table>
<?php
}
}
?>
使用Page类,需要在脚本语言中包含page.inc来调用Display()函数,则再新建立一个home.php:
<?php
require("page.inc"); //或者也可以是include("page.inc")
$homepage=new Page();
$homepage->content="<p>Welcome to the home of TLA Consulting. Please take some time to get to know us.</p> <p>We specialize in serving your business needs and hope to hear from you soon.</p>";
$homepage->Display();
?>
home.php文件将实现如下功能:
1) 使用require()语句包含page.inc的内容,page.inc中包含了Page类的定义。
2) 创建了Page类的一个实例。该实例称为$homepage
。
**3)**设定内容,包括页面显示的文本和HTML标记(这将间接地调用__set()方法)。
4) 在对象$homepage
中调用操作Display(),使页面显示在访问者的浏览器中。
最终运行结果和第五章呈现相同,但是如果使用Page类,在创建新页面的时候只要做少量工作。
类的继承重载
如果希望某一个页面和其他页面的大部分风格相同而只有部分效果有些许差异,则只需要重载某些方法或者属性。
新建立一个services.php:
<?php
require("page.inc");
class ServicesPage extends Page{
private $row2buttons=array(
"Re-engineering"=>"reengineering.php",
"Standards Compliance"=>"standards.php",
"Buzzword Compliance"=>"buzzword.php",
"Mission Statements"=>"mission.php");
public function Display(){
echo "<html>\n<head>\n";
$this->DisplayTitle();
$this->DisplayKeywords();
$this->DisplayStyles();
echo "</head>\n<body>\n";
$this->DisplayHeader();
$this->DisplayMenu($this->buttons);
$this->DisplayMenu($this->row2buttons);
echo $this->content; $this->DisplayFooter();
echo "</body>\n</html>\n";
}
}
$services=new ServicesPage();
$services->content="<p>At TLA Consulting,we offer a number of services.Perhaps the productivity of your employees would improve if we re-engineered your business.Maybe all your business needs is a fresh mission statement,or a new batch of buzzwords.</p>";
$services->Display();
?>
这种做法的好处是显而易见的,不用多次书写同样长的代码函数,而只需要书写要重载的方法即可(该子类重载了Display()操作,改变了输出结果,即第二次调用DisplayMenu()函数,又新创建了一个菜单条)。
五、面向对象其它高级功能
常量的调用—–“::”
假设一个类中的常量:
则以下的语法可以输出该常量(输出3.14159):
静态方法调用—-“::”
可以通过::在 未初始化 该类的情况下调用这个方法,且 注意 不能使用this关键字:
检查类的类型和类型提示—-instanceof()
instanceof()—–检查一个对象是否是特定类的实例
例如,在作为类A的子类而实现的类B例子$b
中,如下语句:
{$b instanceof B}
将返回true.
{$b instanceof A}
将返回true.
{$b instanceof Displayable}
将返回false.
以上这些语句都是假设类A、类B和接口Displayable都位于当前的作用域
延迟静态绑定
允许在一个静态继承的上下文中对一个被调用类的引用。父类可以使用子类重载的静态方法。(注:原来子类重载父类不会影响父类,而此处则是父类可以使用子类的方法了):
注意以下的function一个为public一个为static
class A{
static $name = "Tom";
public function printName(){
echo self::$name."\n";
self::fun();
}
static function fun(){
echo "A Class\n";
}
}
class B extends A{
static $name = "Jon";
static function fun(){
echo "B Class\n";
}
}
$obj = new B();
$obj->printName();
// 输出结果
// Tom
// A Class
复制对象——–clone/__clone()
clone
即:$c=clone $b
;将创建与对象$b具有相同类的副本,而且具有相同的属性值。
** __clone()**
和构造函数和析构函数,定义这个函数时候名字唯一,且使用clone时默认调用 __clone() 。
抽象类
不能被实例化,同样类方法也没有实现,只是提供类方法的声明,没有具体实现:
abstract class A {
abstract function operationX($param1,$param2);
}
注意:包含抽象方法的任何类自身必须是抽象的
方法的重载—– __call()
class overload{
//带有两个参数。第一个包含了被调用的方法名称,而第二个参数包含了传递给该方法的参数数组。
public function __call($method,$p){
if($method=="display"){
if(is_object($p[0])){
$this->displayObject($p[0]);
}
else if(is_array($p[0])){
$this->displayArray($p[0]);
}
else{
$this->displayScalar($p[0]);
}
}
}
}
此时如果一个对象传递给display()方法,可以调用displayObject()方法;如果传递的是一个数组,可以调 用displayArray();如果传递的是其他内容,可以调用displayScalar()方法。
之后要调用以上这段代码,首先必须实例化包含这个__call()的类, 然后再调用display()方法:
$ov=new overload;
$ov->display(array(1,2,3));
$ov->display('cat');
一个单独的非类方法的函数——- __autoload()
可以在任何类声明之外声明这个函数。,可以在任何类声明 之外 声明这个函数。如果实现了这个函数,它将在实例化一个还没有被声明的类时自动调用。
__autoload()
方法的主要用途是尝试包含或请求任何用来初始化所需类的文件。
以下代码实现将包括一个具有与该类相同名称的文件:
function __autoload($name){
include_once $name.".php";
}
类转换成字符串—– __toString()
当尝试打印该类时,可以调用 ** __toString()** 函数:
class Printable{
public $testone;
public $testtwo;
public function __toString(){
//var_export()函数打印出了类中的所有属性值。
return(var_export($this,TRUE));
}
}
$p=new Printable;
echo$p;
通过访问已有类和对象来找到类和对象的结构和内容
即 Reflection(反射)API
显示关于Page类的信息(即,之前编写过的 page.inc 文件,执行以下代码,则会在网页输出 page类 的详细信息:
<?php
//类所在的文件
require_once("page.inc");
// 使用了ReflectionClass类的__toString()方法来打印这个数据
//()中的为类名
$class=new ReflectionClass("Page");
echo"<pre>".$class."</pre>";
?>
六、迭代的实现
<?php
class ObjectIterator implements Iterator{
private $obj;
private $count;
private $currentIndex;
function __construct($obj){
$this->obj=$obj;
$this->count=count($this->obj->data);
}
//将内部数据指针设置回数据开始处
function rewind(){
$this->currentIndex=0;
}
//判断数据指针的当前位置是否还存在更多数据
function valid(){
return $this->currentIndex<$this->count;
}
//返回数据指针的值。
function key(){
return $this->currentIndex;
}
//返回保存在当前数据指针的值。
function current(){
return $this->obj->data[$this->currentIndex];
}
//在数据中移动数据指针的位置。
function next(){
$this->currentIndex++;
}
}
class Object implements IteratorAggregate{
public $data=array();
function __construct($in){
$this->data=$in;
}
function getIterator(){
return new ObjectIterator($this);
}
}
$myObject=new Object(array(2,4,6,8,10));
$myIterator=$myObject->getIterator();
for($myIterator->rewind();$myIterator->valid();$myIterator->next()){
$key=$myIterator->key();
$value=$myIterator->current();
echo $key."=>".$value."<br/>";
}
?>
今天的文章第六章、面向对象的PHP分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/33886.html