類和對(duì)象
類是對(duì)一類事物的描述纹因,對(duì)象是類的實(shí)例。在面向?qū)ο缶幊趟枷胫幸磺惺挛锒际菍?duì)象贵扰,類和對(duì)象是面向?qū)ο缶幊痰闹匾M成部分戈盈。
類的定義
class Person
{
public $name;
function eat(){
echo 'I am eating';
}
function self_introduce(){
echo 'my name is '.$this->name;
}
function get_this(){
if (isset($this)) {
echo 'class is '.get_class($this);
} else {
echo 'there is no $this';
}
}
}
class Book
{
function get_that(){
Person::get_this();
}
}
$tom = new Person();
$tom->name = 'tom';
$tom->eat(); // I am eating
echo '<br/>';
$tom->self_introduce(); // my name is tom
echo '<br/>';
$tom->get_this(); // class is Person
echo '<br/>';
Person::get_this();
// Deprecated: Non-static method Person::get_this() should not be called statically in D:\www\test\test1.php on line 39
// there is no $this
echo '<br/>';
$three_country = new Book;
$three_country->get_that();
// Deprecated: Non-static method Person::get_this() should not be called statically in D:\www\test\test1.php on line 26
// there is no $this
echo '<br/>';
Book::get_that();
// Deprecated: Non-static method Book::get_that() should not be called statically in D:\www\test\test1.php on line 50
// Deprecated: Non-static method Person::get_this() should not be called statically in D:\www\test\test1.php on line 26
// there is no $this
$class_name = 'Person';
$jack = new $class_name();
echo '<pre>';
print_r($jack);
echo '</pre>';
/*
Person Object
(
[name] =>
)
*/
$lucy = $jack;
$lily = &$jack;
$jack = null;
echo '<pre>';
var_dump($jack);
echo '</pre>';
echo '<pre>';
var_dump($lucy);
echo '</pre>';
echo '<pre>';
var_dump($lily);
echo '</pre>';
/*
NULL
object(Person)#1 (1) {
["name"]=>
NULL
}
NULL
*/
$jim = new Person();
$andy = new $jim;
echo '<pre>';
print_r($andy);
echo '</pre>';
echo '<pre>';
var_dump($jim == $andy);
echo '</pre>';
echo '<pre>';
var_dump($jim === $andy);
echo '</pre>';
$john = new Person();
echo '<pre>';
var_dump($jim == $john);
echo '</pre>';
echo '<pre>';
var_dump($jim === $john);
echo '</pre>';
/*
Person Object
(
[name] =>
)
bool(true)
bool(false)
bool(true)
bool(false)
*/
class Programmer extends Person
{
function self_introduce(){
parent::self_introduce();
echo '<br/>';
echo 'I am a programmer, my name is '.$this->name;
}
}
$hanks = new Programmer();
$hanks->name = 'hanks';
$hanks->self_introduce();
// my name is hanks
// I am a programmer, my name is hanks
- 類的定義以關(guān)鍵字
class
開頭奠衔,后面跟著類名,然后是一對(duì)大括號(hào)包圍的類結(jié)構(gòu)塘娶。 - 一個(gè)合法的類名由字母數(shù)字和下劃線組成且不能以數(shù)字開頭归斤。
- 類名通常用大駝峰法命名,花括號(hào)都獨(dú)占一行刁岸,這些不是必須的脏里。
- 類結(jié)構(gòu)中可以包含變量,常量和函數(shù)虹曙,在類中的變量是類的屬性迫横,常量是類常量,函數(shù)是類的方法酝碳。
-
$this
是一個(gè)可以在類內(nèi)部使用的偽變量员淫,是一個(gè)到主叫對(duì)象的引用。 - 函數(shù)
get_class()
用來獲取指定對(duì)象所屬的類击敌。 -
::
是范圍解析操作符,可以用于在類外訪問類的方法拴事。 - 通過
new
關(guān)鍵字來實(shí)例化一個(gè)類成為對(duì)象沃斤。 -
->
是對(duì)象運(yùn)算符,可以用來訪問對(duì)象的屬性和方法刃宵。 - 類名可以使用變量表示衡瓶。
- 可以使用
extends
關(guān)鍵字指定一個(gè)類繼承自另一個(gè)類,繼承的類就有了被繼承類的屬性和方法牲证。在php
中一個(gè)類只能繼承自一個(gè)基類哮针。繼承的屬性和方法可以通過同名屬性和方法去覆蓋,父類中使用final
關(guān)鍵字聲明的方法不能覆蓋,可以使用parent::
來訪問父類中被覆蓋的屬性和方法十厢。覆蓋父類方法時(shí)等太,除了構(gòu)造函數(shù),其它的方法的參數(shù)列表需要和父類保持一致蛮放。
類的屬性
類中的成員變量就是類的屬性缩抡。屬性的聲明要以關(guān)鍵字public
, protected
或private
開頭,后面跟著一個(gè)變量聲明包颁,作為屬性的變量可以進(jìn)行初始化瞻想,public
, protected
或private
表示了屬性的可見性。
$shanghai = 'shanghai';
const JIANGSU = 'jiangsu';
class Person
{
// $name; // Parse error: syntax error, unexpected '$name' (T_VARIABLE), expecting function (T_FUNCTION) or const (T_CONST) in
var $name;
public $sex;
public $age = 12;
public $count = 1 + 2;
public $introduction = 'I am a '.'programmer';
public $motto = <<<EOD
impossible is nothing
EOD;
// public $hello = self::return_string(); // Fatal error: Constant expression contains invalid operations in
// public $city = $shanghai; // Fatal error: Constant expression contains invalid operations in
public static $new_name = 'another name';
// public $another_name = self::$new_name; // Fatal error: Constant expression contains invalid operations
public $province = JIANGSU;
public $area = ['putuo', 'minhang'];
public $mobile = <<<'EOD'
11111111111
EOD;
static function return_string(){
return 'hello';
}
function return_hello(){
return self::return_string();
}
function return_shanghai(){
return $shanghai;
}
function return_new_name(){
return self::$new_name;
}
}
$tom = new Person();
echo '<pre>';
var_dump($tom->name); // NULL
echo '</pre>';
echo '<pre>';
var_dump($tom->sex); // NULL
echo '</pre>';
echo $tom->age; // 12
echo '<br/>';
echo $tom->introduction; // I am a programmer
echo '<br/>';
echo $tom->motto; // impossible is nothing
echo '<br/>';
echo Person::return_string(); // hello
echo '<br/>';
echo $tom->return_hello(); // hello
echo '<br/>';
echo $tom->return_shanghai(); // Notice: Undefined variable: shanghai in
echo '<br/>';
echo $tom->return_new_name(); // another name
echo '<br/>';
echo $tom->count; // 3
echo '<br/>';
echo JIANGSU; // jiangsu
echo '<br/>';
echo $tom->province; // jiangsu
echo '<br/>';
echo ANHUI;
// Notice: Use of undefined constant ANHUI - assumed 'ANHUI' in
// ANHUI
echo '<br/>';
echo '<pre>';
print_r($tom->area);
echo '</pre>';
/*
Array
(
[0] => putuo
[1] => minhang
)
*/
echo '<br/>';
echo $tom->mobile; // 11111111111
- 可以通過對(duì)象運(yùn)算符
->
訪問非靜態(tài)屬性娩嚼,靜態(tài)屬性要通過::
來訪問癞季。 - 可以通過關(guān)鍵字
var
來聲明屬性,這是php5
之前用法吃衅,在php5
的某些版本這種用法被廢棄并會(huì)產(chǎn)生報(bào)錯(cuò)贫悄,如果沒有使用public
,protected
或private
等修飾符,僅使用var
聲明的變量會(huì)被認(rèn)為是public
的竿音。 - 類中的關(guān)鍵字
self
表示類本身和屎。
類常量
在類中定義的常量被稱為類常量。
$count = 2;
class Person
{
const head_number = 1;
// define(eyes_number, 2); // Parse error: syntax error, unexpected 'define' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST) in
const EYES_NUMBER = 2;
// const 1hands_number = 1; // Parse error: syntax error, unexpected '1' (T_LNUMBER) in
const _handsnumber2 = 2;
// const hands_@number = 3; // Parse error: syntax error, unexpected '@', expecting '=' in
// const hands_number; // Parse error: syntax error, unexpected ';', expecting '=' in
const hands_number = 1 + 1;
public static $count = 2;
// const legs_number = $count; // Fatal error: Constant expression contains invalid operations in
// const legs_number = self::$count; // Fatal error: Constant expression contains invalid operations in
// const legs_number = self::return_count(); // Fatal error: Constant expression contains invalid operations in
const hello = <<<EOD
hello
EOD;
const world = <<<'EOD'
world
EOD;
const arr = [0, 1, 2];
static function return_count(){
return self::$count;
}
function return_head_number(){
return self::head_number;
}
}
echo Person::head_number; // 1
echo '<br/>';
// echo Person::eyes_number; // Fatal error: Uncaught Error: Undefined class constant 'eyes_number' in
// echo Person::eyes_number; // Fatal error: Uncaught Error: Undefined class constant 'eyes_number' in
echo Person::EYES_NUMBER; // 2
echo '<br/>';
echo Person::_handsnumber2; // 2
echo '<br/>';
echo Person::hands_number; // 2
echo '<br/>';
$tom = new Person;
echo $tom->return_head_number(); // 1
$class_name = 'Person';
echo '<br/>';
echo $class_name::head_number; // 1
echo '<br/>';
echo $tom::head_number; // 1
echo '<br/>';
// echo $tom->head_number; // Notice: Undefined property: Person::$head_number in
echo $tom::hello; // hello
echo '<br/>';
echo $tom::world; // world
echo '<br/>';
echo '<pre>';
print_r($tom::arr);
echo '</pre>';
/*
Array
(
[0] => 0
[1] => 1
[2] => 2
)
*/
- 類常量必須是一個(gè)定值春瞬,不能是變量柴信,類屬性或是函數(shù)調(diào)用結(jié)果。
- 可以通過
const
關(guān)鍵字來定義類常量但是不可以使用define()
函數(shù)宽气。 - 類常量不用
$
符作為前引随常,類常量名由數(shù)字字母下劃線構(gòu)成但是不能以數(shù)字開頭,類常量名區(qū)分大小寫萄涯。 - 常量聲明時(shí)就要初始化值绪氛。
- 在類外部訪問常量可以聽過類或者對(duì)象使用
::
運(yùn)算符來進(jìn)行,在類內(nèi)部訪問使用常量可以通過self::
來進(jìn)行涝影,self
表示類本身枣察。
類的繼承
繼承是面向?qū)ο缶幊虝r(shí)實(shí)現(xiàn)代碼復(fù)用的重要途徑,繼承會(huì)影響到類與類燃逻,對(duì)象與對(duì)象之間的關(guān)系序目。通過繼承可以讓一個(gè)類擁有和擴(kuò)展另一個(gè)類的功能,前者被稱為子類伯襟,后者被稱為父類或基類猿涨。
class Person
{
public $name = 'stone';
protected $sex;
private $age;
public function return_name(){
return $this->name;
}
protected function set_name($name){
$this->name = $name;
}
private function return_class_name(){
return 'Person';
}
public function return_string(){
return 'hello';
}
}
$tom = new Person;
echo '<pre>';
print_r($tom);
echo '</pre>';
/*
Person Object
(
[name] => stone
[sex:protected] =>
[age:Person:private] =>
)
*/
$tom->name = 'tom';
echo $tom->return_name(); // tom
echo '<br/>';
echo $tom->return_string(); // hello
class Programmer extends Person
{
function return_string(){
return 'world';
}
}
$stone = new Programmer;
echo '<pre>';
print_r($stone);
echo '</pre>';
/*
Programmer Object
(
[name] => stone
[sex:protected] =>
[age:Person:private] =>
)
*/
var_dump($stone->introduction);
// Notice: Undefined property: Programmer::$introduction in
// NULL
echo '<br/>';
$stone->introduction = 'I am a programmer';
echo $stone->introduction; // I am a programmer
echo '<br/>';
var_dump($stone->name); // string(5) "stone"
echo '<br/>';
echo $stone->return_name(); // stone
echo '<br/>';
echo $stone->return_string(); // world
- 子類會(huì)繼承父類所有公有和受保護(hù)的方法,子類可以通過重寫來覆蓋父類的方法姆怪。
- 父類必須在子類之前被聲明叛赚。
- 繼承需要使用關(guān)鍵字
extends
澡绩。 - 父類的屬性也會(huì)被子類繼承。
構(gòu)造函數(shù)和析構(gòu)函數(shù)
構(gòu)造函數(shù)用于在實(shí)例化一個(gè)類為對(duì)象時(shí)做一些初始化的操作俺附,構(gòu)造函數(shù)是類中一個(gè)在新建對(duì)象時(shí)會(huì)被自動(dòng)調(diào)用的方法肥卡。析構(gòu)函數(shù)在對(duì)象所有引用被刪除或?qū)ο蟊伙@示銷毀時(shí)會(huì)被調(diào)用,析構(gòu)函數(shù)適合做一些清理和收尾工作昙读。
class Person
{
function __construct(){
echo 'this is a construct';
}
function __destruct(){
echo 'this is a destruct';
echo '<br/>';
}
}
$tom = new Person; // this is a construct
class Programmer extends Person
{
function __construct(){
parent::__construct();
echo '<br/>';
echo 'this is a programmer construct';
}
function __destruct(){
parent::__destruct();
echo 'this is a programmer destruct';
echo '<br/>';
}
}
echo '<br/>';
$stone = new Programmer;
/*
this is a construct
this is a programmer construct
*/
class Saler extends Person
{
}
echo '<br/>';
$jim = new Saler; // this is a construct
class Animal
{
public $name;
function __construct($name){
$this->name = $name;
}
function get_name(){
return $this->name;
}
function __destruct(){
$this->name = null;
echo 'this is an Animal destruct';
echo '<br/>';
}
}
$nick = new Animal('nick');
echo '<br/>';
echo $nick->get_name(); // nick
echo '<br/>';
/*
this is an Animal destruct
this is a destruct
this is a destruct
this is a programmer destruct
this is a destruct
*/
- 構(gòu)造函數(shù)的名稱為
__construct
召调。 - 析構(gòu)函數(shù)的名稱為
__destruct
。 - 子類可以繼承父類的非
private
構(gòu)造函數(shù)蛮浑,在子類覆蓋了父類的構(gòu)造函數(shù)時(shí)如果要調(diào)用父類的構(gòu)造函數(shù)可以通過使用parent::__construct
來進(jìn)行唠叛。 - 構(gòu)造函數(shù)可以有參數(shù),析構(gòu)函數(shù)不可以有參數(shù)沮稚,構(gòu)造函數(shù)和析構(gòu)函數(shù)都不能有返回值艺沼。
- 子類可以繼承父類的非
private
析造函數(shù),在子類覆蓋了父類的析造函數(shù)時(shí)如果要調(diào)用父類的析造函數(shù)可以通過使用parent::__destruct
來進(jìn)行蕴掏。
訪問控制
通過訪問控制可以指定類的成員(包括屬性和方法)的訪問范圍障般,可以通過在類成員前面加上修飾符public
, protected
或private
來指定訪問控制。
class Person
{
var $name = 'tom';
protected $sex = 'male';
private $age = 30;
public $introduction = 'I am a person';
function echo_info(){
echo $this->name;
echo '<br/>';
echo $this->sex;
echo '<br/>';
echo $this->age;
echo '<br/>';
echo $this->introduction;
}
function a_public_function(){
echo 'this is a public function in Person';
echo '<br/>';
}
protected function a_protected_function(){
echo 'this is a protected function in Person';
echo '<br/>';
}
private function a_private_function(){
echo 'this is a private function in Person';
echo '<br/>';
}
public function show_function(){
$this->a_public_function();
$this->a_protected_function();
$this->a_private_function();
}
}
$tom = new Person();
echo '<pre>';
print_r($tom);
echo '</pre>';
/*
Person Object
(
[name] => tom
[sex:protected] => male
[age:Person:private] => 30
[introduction] => I am a person
)
*/
$tom->echo_info();
/*
tom
male
30
I am a person
*/
echo '<br/>';
echo $tom->name; // tom
echo '<br/>';
// echo $tom->sex; // Fatal error: Uncaught Error: Cannot access protected property Person::$sex in
echo '<br/>';
// echo $tom->age; // Fatal error: Uncaught Error: Cannot access private property Person::$age in
echo '<br/>';
echo $tom->introduction; // I am a person
echo '<br/>';
$tom->a_public_function(); // this is a public function in Person
// $tom->a_protected_function(); // Fatal error: Uncaught Error: Call to protected method Person::a_protected_function() from context '' in
// $tom->a_private_function(); // Fatal error: Uncaught Error: Call to private method Person::a_private_function() from context '' in
$tom->show_function();
/*
this is a public function in Person
this is a protected function in Person
this is a private function in Person
*/
class Programmer extends Person
{
public $name = 'stone';
function echo_info(){
echo $this->name;
echo '<br/>';
echo $this->sex;
echo '<br/>';
echo $this->age;
echo '<br/>';
echo $this->introduction;
echo '<br/>';
}
public function programmer_show_function(){
$this->a_public_function();
$this->a_protected_function();
// $this->a_private_function(); // Fatal error: Uncaught Error: Call to private method Person::a_private_function() from context 'Programmer' in
}
}
$stone = new Programmer;
echo '<pre>';
print_r($stone);
echo '</pre>';
/*
Programmer Object
(
[name] => stone
[sex:protected] => male
[age:Person:private] => 30
[introduction] => I am a person
)
*/
echo $stone->name; // stone
echo '<br/>';
// echo $stone->sex; // Fatal error: Uncaught Error: Cannot access protected property Programmer::$sex in
echo '<br/>';
echo $stone->age; // Notice: Undefined property: Programmer::$age in
echo '<br/>';
$stone->echo_info();
/*
stone
male
Notice: Undefined property: Programmer::$age in D:\www\test\test1.php on line 59
I am a person
*/
$stone->a_public_function(); // this is a public function in Person
// $stone->a_protected_function(); // Fatal error: Uncaught Error: Call to protected method Person::a_protected_function() from context '' in
// $stone->a_private_function(); // Fatal error: Uncaught Error: Call to private method Person::a_private_function() from context '' in
$stone->show_function();
/*
this is a public function in Person
this is a protected function in Person
this is a private function in Person
*/
$stone->programmer_show_function();
/*
this is a public function in Person
this is a protected function in Person
*/
class Saler extends Person
{
function a_public_function(){
echo 'this is a public function in Saler';
echo '<br/>';
}
protected function a_protected_function(){
echo 'this is a protected function in Saler';
echo '<br/>';
}
private function a_private_function(){
echo 'this is a private fucntion in Saler';
echo '<br/>';
}
public function saler_show_function(){
$this->a_public_function();
$this->a_protected_function();
$this->a_private_function();
}
}
$jim = new Saler;
$jim->a_public_function(); // this is a public function in Saler
// $jim->a_protected_function(); // Fatal error: Uncaught Error: Call to protected method Saler::a_protected_function() from context '' in
// $jim->a_private_function(); // Fatal error: Uncaught Error: Call to private method Saler::a_private_function() from context '' in
$jim->show_function();
/*
this is a public function in Saler
this is a protected function in Saler
this is a private function in Person
*/
$jim->saler_show_function();
/*
this is a public function in Saler
this is a protected function in Saler
this is a private fucntion in Saler
*/
class Animal
{
private $name;
function __construct($name){
$this->name = $name;
}
private function echo_name(){
echo 'my name is '.$this->name;
echo '<br/>';
}
function access_private(Animal $animal){
// $animal->name = 'tom';
$animal->echo_name();
}
}
$jack = new Animal('jack');
// $jack->echo_name(); // Fatal error: Uncaught Error: Call to private method Animal::echo_name() from context '' in
// echo $jack->name; // Fatal error: Uncaught Error: Cannot access private property Animal::$name in
$jack->access_private(new Animal('lucy')); // my name is lucy
- 被
public
修飾的類成員是公有的盛杰,可以在任何地方被訪問挽荡。 - 被
protected
修飾的類成員是受保護(hù)的,可以被類本身即供,子類和父類訪問定拟。 - 被
private
修飾的類成員是私有的,只能被類本身訪問逗嫡。 - 沒有被訪問控制關(guān)鍵字修飾的類成員被認(rèn)為是公有的青自,即
public
。 - 子類會(huì)繼承父類的公有和受保護(hù)的類成員驱证,可以重寫這些這些類成員延窜。
- 若想訪問其它對(duì)象的私有或受保護(hù)的屬性和方法則可以通過將對(duì)象作為參數(shù)傳遞給另一個(gè)對(duì)象的方法來實(shí)現(xiàn)。
類的自動(dòng)加載
通過類的自動(dòng)加載可以避免冗長的文件加載列表抹锄,在php
中可以使用函數(shù)spl_autoload_register()
來完成類的自動(dòng)加載逆瑞。
// Person.php
class Person
{
public $name;
function say_something(){
echo 'I say something';
echo '<br/>';
}
}
// Programmer.php
class Programmer extends Person
{
public $name;
function coding(){
echo 'I am coding...';
echo '<br/>';
}
}
// Animal.php
class Animal
{
public $name;
function eat(){
echo 'I am eating';
}
}
// index.php
/*require_once('./Person.php');
require_once('./Programmer.php');
require_once('./Animal.php');*/
spl_autoload_register(function($class_name){
require_once $class_name.'.php';
});
$tom = new Person();
$tom->say_something(); // I say something
$stone = new Programmer();
$stone->say_something(); // I say something
$stone->coding(); // I am coding...
$jack = new Animal;
$jack->eat(); // I am eating
范圍解析操作符
在php
中,由兩個(gè)冒號(hào)組成的運(yùn)算符::
被稱為范圍解析操作符伙单,通過::
可以訪問類的靜態(tài)成員和類常量呆万,還可以通過范圍解析操作符來覆蓋類的屬性和方法。
class Person
{
// const CONST_VAR; // Parse error: syntax error, unexpected ';', expecting '=' in
const CONST_VAR = 'A CONST VARIABLE';
static function return_const(){
// return $this->CONST_VAR; // Fatal error: Uncaught Error: Using $this when not in object context in
return self::CONST_VAR;
}
protected function a_function(){
echo self::return_const();
echo '<br/>';
echo 'this is a protected funtion in Person';
echo '<br/>';
}
}
echo Person::CONST_VAR; // A CONST VARIABLE
echo '<br/>';
// echo Person::return_const(); // Fatal error: Uncaught Error: Using $this when not in object context in
$tom = new Person;
// echo $tom->return_const(); // Fatal error: Uncaught Error: Using $this when not in object context in
echo Person::return_const(); // A CONST VARIABLE
echo '<br/>';
$class_person = 'Person';
echo $class_person::CONST_VAR; // A CONST VARIABLE
echo '<br/>';
echo $class_person::return_const(); // A CONST VARIABLE
echo '<br/>';
class Programmer extends Person
{
public static $static_var = 'a static variable';
public static function echo_const_static(){
// echo self::CONST_VAR; // A CONST VARIABLE
echo parent::CONST_VAR;
echo '<br/>';
echo self::$static_var;
echo '<br/>';
}
function a_function(){
parent::a_function();
echo 'this is a function in Programmer';
echo '<br/>';
}
}
$stone = new Programmer;
// echo $stone->static_var;
// Notice: Accessing static property Programmer::$static_var as non static in
// Notice: Undefined property: Programmer::$static_var in
$stone->echo_const_static();
// A CONST VARIABLE
// a static variable
echo Programmer::$static_var;
echo '<br/>'; // a static variable
Programmer::echo_const_static();
/*
A CONST VARIABLE
a static variable
*/
$class_programmer = 'Programmer';
echo $class_programmer::$static_var; // a static variable
echo '<br/>';
$stone->a_function();
/*
A CONST VARIABLE
this is a protected funtion in Person
this is a function in Programmer
*/
- 可以通過變量來引用類车份,但是變量的值不能是
self
,parent
或static
。 - 通過
::
運(yùn)算符可在類內(nèi)部訪問類的本身的常量和靜態(tài)方法牡彻,可以訪問父類的類常量和方法扫沼。
本文首發(fā)于公眾號(hào):programmer_cc出爹,轉(zhuǎn)載請(qǐng)注明出處。