## 基本概念
### class
每個類的定義都以關鍵字class開頭,后面跟著類名,后面跟著一對花括號,里面包含有類的屬性與方法的定義。
類名可以是任何非PHP[保留字](http://php.net/manual/zh/reserved.php)的合法標簽。一個合法類名以字母或下劃線開頭,后面跟著若干字母,,數字或下劃線。以正則表達式表示為:*\[a-zA-Z\_\\x7f-\\xff\]\[a-zA-Z0-9\_\\x7f-\\xff\]\**。
一個類可以包含有屬于自己的[常量](http://php.net/manual/zh/language.oop5.constants.php),[變量](http://php.net/manual/zh/language.oop5.properties.php)(稱為“屬性”)以及函數(稱為“方法”)。
**Example #1**簡單的類定義
```
<?php
class SimpleClass
{
// 聲明屬性
public $var = 'a default value';
// 聲明方法
public function displayVar(){
echo $this->var;
}
}
```
當一個方法在類定義內部被調用時,有一個可用的偽變量$this。$this是一個到主叫對象的引用(通常是該方法所從屬的對象,但如果是從第二個對象[靜態](http://php.net/manual/zh/language.oop5.static.php)調用時也可能是另一個對象)。
**Example #2 $this 偽變量的示例**
We're assuming that error\_reporting is disabled for this example; otherwise the following code would trigger deprecated and strict notices, respectively, depending on the PHP version.
```
<?php
class?A
{
????function?foo()
????{
????????if?(isset($this))?{
????????????echo?'$this?is?defined?(';
????????????echo?get_class($this);
????????????echo?")\n";
????????}?else?{
????????????echo?"\$this?is?not?defined.\n";
????????}
????}
}
class?B
{
????function?bar()
????{
????????A::foo();
????}
}
$a?=?new?A();
$a->foo();
A::foo();
$b?=?new?B();
$b->bar();
B::bar();
?>
```
Output of the above example in PHP 5:
~~~
$this is defined (A)
$this is not defined.
$this is defined (B)
$this is not defined.
~~~
Output of the above example in PHP 7:
~~~
$this is defined (A)
$this is not defined.
$this is not defined.
$this is not defined.
~~~
### new
要創建一個類的實例,必須使用 *new* 關鍵字。當創建新對象時該對象總是被賦值,除非該對象定義了[構造函數](http://php.net/manual/zh/language.oop5.decon.php)并且在出錯時拋出了一個[異常](http://php.net/manual/zh/language.exceptions.php)。類應在被實例化之前定義(某些情況下則必須這樣)。
如果在 *new* 之后跟著的是一個包含有類名的字符串 [string](http://php.net/manual/zh/language.types.string.php),則該類的一個實例被創建。如果該類屬于一個命名空間,則必須使用其完整名稱。
**Example #3 創建實例**
```
<?php
$instance?=?new?SimpleClass();
//?也可以這樣做:
$className?=?'Foo';
$instance?=?new?$className();?//?Foo()
?>
```
在類定義內部,可以用 *new self* 和 *new parent* 創建新對象。
當把一個對象已經創建的實例賦給一個新變量時,新變量會訪問同一個實例,就和用該對象賦值一樣。此行為和給函數傳遞入實例時一樣。可以用[克隆](http://php.net/manual/zh/language.oop5.cloning.php)給一個已創建的對象建立一個新實例。
**Example #4 對象賦值**
```
<?php
$instance?=?new?SimpleClass();
$assigned???=??$instance;
$reference??=&?$instance;
$instance->var?=?'$assigned?will?have?this?value';
$instance?=?null;?//?$instance?and?$reference?become?null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
```
以上例程會輸出:
~~~
NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "$assigned will have this value"
}
~~~
PHP 5.3.0 引進了兩個新方法來創建一個對象的實例:
**Example #5 創建新對象**
```
<?php
class?Test
{
????static?public?function?getNew()
????{
????????return?new?static;
????}
}
class?Child?extends?Test
{}
$obj1?=?new?Test();
$obj2?=?new?$obj1;
var_dump($obj1?!==?$obj2);
$obj3?=?Test::getNew();
var_dump($obj3?instanceof?Test);
$obj4?=?Child::getNew();
var_dump($obj4?instanceof?Child);
?>
```
以上例程會輸出:
~~~
bool(true)
bool(true)
bool(true)
~~~
PHP 5.4.0 起,可以通過一個表達式來訪問新創建對象的成員:
**Example #6 訪問新創建對象的成員**
```
<?php
echo?(new?DateTime())->format('Y');
?>
```
以上例程的輸出類似于:
~~~
2016
~~~
### Properties and methods
Class properties and methods live in separate "namespaces", so it is possible to have a property and a method with the same name. Referring to both a property and a method has the same notation, and whether a property will be accessed or a method will be called, solely depends on the context, i.e. whether the usage is a variable access or a function call.
**Example #7 Property access vs. method call**
```
<?php
class?Foo
{
????public?$bar?=?'property';
????
????public?function?bar()?{
????????return?'method';
????}
}
$obj?=?new?Foo();
echo?$obj->bar,?PHP_EOL,?$obj->bar(),?PHP_EOL;
```
以上例程會輸出:
~~~
property
method
~~~
That means that calling an [anonymous function](http://php.net/manual/zh/functions.anonymous.php) which has been assigned to a property is not directly possible. Instead the property has to be assigned to a variable first, for instance. As of PHP 7.0.0 it is possible to call such a property directly by enclosing it in parentheses.
**Example #8 Calling an anonymous function stored in a property**
```
<?php
class?Foo
{
????public?$bar;
????
????public?function?__construct()?{
????????$this->bar?=?function()?{
????????????return?42;
????????};
????}
}
$obj?=?new?Foo();
//?as?of?PHP?5.3.0:
$func?=?$obj->bar;
echo?$func(),?PHP_EOL;
//?alternatively,?as?of?PHP?7.0.0:
echo?($obj->bar)(),?PHP_EOL;
```
以上例程會輸出:
~~~
42
~~~
### extends
一個類可以在聲明中用 *extends* 關鍵字繼承另一個類的方法和屬性。PHP不支持多重繼承,一個類只能繼承一個基類。
被繼承的方法和屬性可以通過用同樣的名字重新聲明被覆蓋。但是如果父類定義方法時使用了 [final](http://php.net/manual/zh/language.oop5.final.php),則該方法不可被覆蓋。可以通過 [parent::](http://php.net/manual/zh/language.oop5.paamayim-nekudotayim.php) 來訪問被覆蓋的方法或屬性。
當覆蓋方法時,參數必須保持一致否則 PHP 將發出 **`E_STRICT`** 級別的錯誤信息。但構造函數例外,構造函數可在被覆蓋時使用不同的參數。
**Example #9 簡單的類繼承**
```
<?php
class?ExtendClass?extends?SimpleClass
{
????//?Redefine?the?parent?method
????function?displayVar()
????{
????????echo?"Extending?class\n";
????????parent::displayVar();
????}
}
$extended?=?new?ExtendClass();
$extended->displayVar();
?>
```
以上例程會輸出:
~~~
Extending class
a default value
~~~
### ::class
自 PHP 5.5 起,關鍵詞 *class* 也可用于類名的解析。使用 *ClassName::class* 你可以獲取一個字符串,包含了類 *ClassName* 的完全限定名稱。這對使用了 [命名空間](http://php.net/manual/zh/language.namespaces.php) 的類尤其有用。
**Example #10 類名的解析**
```
<?php
namespace?NS?{
????class?ClassName?{
????}
????
????echo?ClassName::class;
}
?>
```
以上例程會輸出:
~~~
NS\ClassName
~~~
> **Note**:
>
> The class name resolution using *::class* is a compile time transformation. That means at the time the class name string is created no autoloading has happened yet. As a consequence, class names are expanded even if the class does not exist. No error is issued in that case.
- 序言
- 簡介
- PHP是什么?
- PHP能做什么?
- 基本語法
- 類型
- boolean(布爾型)
- integer(整型)
- float(浮點型)
- string(字符串)
- array(數組)
- object(對象)
- callable(可調用)
- resource(資源)
- NULL(無類型)
- 偽類型
- 類型轉換的判別
- 變量
- 基礎
- 預定義變量
- 變量范圍
- 可變變量
- 來自PHP之外的變量
- 常量
- 語法
- 魔術常量
- 表達式
- 運算符
- 運算符優先級
- 算術運算符
- 賦值運算符
- 位運算符
- 比較運算符
- 錯誤控制運算符
- 執行運算符
- 遞增/遞減運算符
- 邏輯運算符
- 字符串運算符
- 數組運算符
- 類型運算符
- 流程控制
- if
- else
- elseif/else if
- 流程控制的替代語法
- while
- do-whille
- for
- foreach
- break
- continue
- switch
- declare
- return
- require
- include
- require_once
- include_once
- goto
- 函數
- 用戶自定義函數
- 函數的參數
- 返回值
- 可變函數
- 內部 (內置)函數
- 匿名函數
- 類與對象
- 簡介
- 基本概念
- 屬性
- 類的自動加載
- 構造函數
- 訪問控制(可見性)