《PHP对象、模式与实践》之对象
1.php与对象
知识点:
a.关于引用赋值
$other = &$my_obj;
//按照引用复制,指向相同对象。
例子:
<?php $my_obj = 1; echo $my_obj."<br/>";//1 $other = &$my_obj; echo $other."<br/>";//1 $my_obj = 2; echo $other;//2 //按照引用复制,指向相同对象。
2.类与对象
知识点
a.类是对象的模板,对象是类实现的实例
变量函数对应类中的属性和方法。
和函数不同的是,方法必须在类体中声明。
$this是伪变量,可以将类指向一个对象实例。
b.一个类实例
<?php class ShopProduct{ public $title; public $producerMainName; public $producerFirstName; public $price = 0; function __construct($title,$firstName,$mainName,$price){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } } $product1 = new ShopProduct("My pro","Willa","Tom",5.99); print "author:{$product1->getProducer()}\n";
输出:
author:Willa Tom
一个更复杂的例子
<?php class CdProduct{ public $playLength; public $title; public $producerMainName; public $producerFirstName; public $price; function __construct($title,$firstName,$mainName,$price,$playLength){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; $this->playLength = $playLength; } function getPlayLength(){ return $this->playLength; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":playing time -{$this->playLength}"; return $base; } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } } class BookProduct{ public $numPages; public $title; public $producerMainName; public $producerFirstName; public $price; function __construct($title,$firstName,$mainName,$price,$numPages){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; $this->numPages = $numPages; } function getnumPages(){ return $this->numPages; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":page count -{$this->numPages}"; return $base; } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } } class ShopProduct{ public $title; public $producerMainName; public $producerFirstName; public $price = 0; function __construct($title,$firstName,$mainName,$price){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; }
function getSummaryLine(){
$base = "{$this->title}({$this->producerMainName},";
$base .= "{$this->producerFirstName})";
return $base;
}
function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } } $product1 = new ShopProduct("My pro","Willa","Tom",5.99); print "author:{$product1->getProducer()}<br/>"; $product2 = new CdProduct("My pro","Willa","Tom",5.99,1); print "PlayLength:{$product2->getPlayLength()}<br/>"; $product3 = new BookProduct("My pro","Willa","Tom",5.99,10); print "numPages:{$product3->getnumPages()}<br/>";
结果:
author:Willa Tom
PlayLength:1
numPages:10
点评:这三个类写在同一个文件下面,说明php支持一个文件包含多个类。只是这样有点不太好,最好单独一个文件,把他们引入进来,然后创建对象,使用。
这三个类还有一个缺点就是,代码重复了,每个类中都有getSummaryLine()方法,和getProducer()方法。这样就冗余了,这个时候怎么办呢?
如果类之间有一定的继承关系,可以用继承这种机制,当然也不要继承很多层次,那样太深了也不好。
适当的继承能够让类更简洁,更利索!
下面是继承的案例:
<?php class ShopProduct{ public $numPages; public $playLength; public $title; public $producerMainName; public $producerFirstName; public $price; function __construct($title,$firstName,$mainName,$price,$numPages=0,$playLength=0){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; $this->numPages = $numPages; $this->playLength = $playLength; } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } function getSummaryLine(){ $base = "$this->title({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; return $base; } } class CdProduct extends ShopProduct{ function getPlayLength(){ return $this->playLength; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":playing time {$this->playLength}"; return $base; } } class BookProduct extends ShopProduct{ function getnumPages(){ return $this->numPages; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":page count {$this->numPages}"; return $base; } } $product1 = new ShopProduct("My pro","Willa","Tom",5.99); print "SummaryLine:{$product1->getSummaryLine()}<br/>"; $product2 = new CdProduct("My pro","Willa","Tom",5.99,null,5); print "SummaryLine:{$product2->getSummaryLine()}<br/>"; $product3 = new BookProduct("My pro","Willa","Tom",5.99,10,null); print "SummaryLine:{$product3->getSummaryLine()}<br/>";
结果:
SummaryLine:My pro(Tom,Willa)
SummaryLine:My pro(Tom,Willa):playing time 5
SummaryLine:My pro(Tom,Willa):page count 10
点评:子类继承父类的属性和构造行数,以及一些基本的函数。
继承之后,可以覆盖父类的函数,也可以新建自己的函数。继承可以避免类内容的重复,代码的重复。
继续改造,子类中也有自己的构造方法。
在子类中定义构造方法时,需要传递参数给父类的构造方法,否则你得到的可能是一个构造不完整的对象。
<?php class ShopProduct{ public $title; public $producerMainName; public $producerFirstName; public $price; function __construct($title,$firstName,$mainName,$price){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } function getSummaryLine(){ $base = "$this->title({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; return $base; } } class CdProduct extends ShopProduct{ public $playLength; function __construct($title,$firstName,$mainName,$price,$playLength){ parent::__construct($title,$firstName,$mainName,$price);//继承父类的构造函数 $this->playLength = $playLength; } function getPlayLength(){ return $this->playLength; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":playing time {$this->playLength}"; return $base; } } class BookProduct extends ShopProduct{ public $numPages; function __construct($title,$firstName,$mainName,$price,$numPages){ parent::__construct($title,$firstName,$mainName,$price); $this->numPages = $numPages; } function getnumPages(){ return $this->numPages; } function getSummaryLine(){ $base = "{$this->title}({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; $base .= ":page count {$this->numPages}"; return $base; } } $product1 = new ShopProduct("My pro","Willa","Tom",5.99); print "SummaryLine:{$product1->getSummaryLine()}<br/>"; $product2 = new CdProduct("My pro","Willa","Tom",5.99,5); print "SummaryLine:{$product2->getSummaryLine()}<br/>"; $product3 = new BookProduct("My pro","Willa","Tom",5.99,10); print "SummaryLine:{$product3->getSummaryLine()}<br/>";
结果同上一个效果一点,这里面每个子类都有自己的构造方法了,同时继承了父类中的构造方法。这样就保证了子类的灵活性。不完全受制于父类。
进一步添加访问权限设置,
<?php class ShopProduct{ private $title; private $producerMainName; private $producerFirstName; protected $price; private $discount = 0; function __construct($title,$firstName,$mainName,$price){ $this->title = $title; $this->producerFirstName = $firstName; $this->producerMainName = $mainName; $this->price = $price; } public function getProducerFirstName(){ return $this->producerFirstName; } public function getProducerMainName(){ return $this->producerMainName; } public function setDiscount($num){ $this->discount = $num; } public function getDiscount(){ return $this->discount; } public function getTitle(){ return $this->title; } public function getPrice(){ return ($this->price - $this->discount); } function getProducer(){ return $this->producerFirstName." ".$this->producerMainName; } function getSummaryLine(){ $base = "$this->title({$this->producerMainName},"; $base .= "{$this->producerFirstName})"; return $base; } } class CdProduct extends ShopProduct{ private $playLength; function __construct($title,$firstName,$mainName,$price,$playLength){ parent::__construct($title,$firstName,$mainName,$price);//继承父类的构造函数 $this->playLength = $playLength; } function getPlayLength(){ return $this->playLength; } function getSummaryLine(){ $base = parent::getSummaryLine(); $base .= ":playing time {$this->playLength}"; return $base; } } class BookProduct extends ShopProduct{ private $numPages = 0; function __construct($title,$firstName,$mainName,$price,$numPages){ parent::__construct($title,$firstName,$mainName,$price); $this->numPages = $numPages; } function getnumPages(){ return $this->numPages; } function getSummaryLine(){ $base = parent::getSummaryLine(); $base .= ":page count {$this->numPages}"; return $base; } } $product1 = new ShopProduct("My pro","Willa","Tom",5.99); print "SummaryLine:{$product1->getSummaryLine()}<br/>"; $product2 = new CdProduct("My pro","Willa","Tom",5.99,5); print "SummaryLine:{$product2->getSummaryLine()}<br/>"; $product3 = new BookProduct("My pro","Willa","Tom",5.99,10); print "SummaryLine:{$product3->getSummaryLine()}<br/>";
点评:一般属性设置为私有的,只能通过方法来设置和获取,这样能保证安全性。