第六章、面向对象的PHP

一、类的结构

限定符------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类中的publicprotect定义的属性和方法,同时还可以在B类中自定义属于B类的属性和方法。
重载
假设有类A:
在这里插入图片描述
,如果需要改变$attribute的默认值,并为operation()操作提供新的功能,可以创 建类B,它重载了$attributeoperation()方法,注意,这种方法不会影响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/>";
}
?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值