php對象

php.netphp

對象

在類定義內部,能夠用 new self 和 new parent 建立新對象。
當把一個對象已經建立的實例賦給一個新變量時,新變量會訪問同一個實例,就和用該對象賦值同樣。能夠用克隆給一個已建立的對象創建一個新實例。數組

<?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 引進了兩個新方法來建立一個對象的實例:this

<?php
class Test
{
    static public function getNew()
    {
        return new static;
    }
}
$obj1 = new Test();
$obj2 = new $obj1;  //第一種
$obj3 = Test::getNew();

自 PHP 5.5 起,使用 ClassName::class 你能夠獲取一個字符串,包含了類 ClassName 的徹底限定名稱。這對使用了 命名空間 的類尤爲有用。.net

類常量

能夠把在類中始終保持不變的值定義爲常量。在定義和使用常量的時候不須要使用 $ 符號debug

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

靜態屬性不能經過一個類已實例化的對象來訪問(但靜態方法能夠)code

抽象類

任何一個類,若是它裏面至少有一個方法是被聲明爲抽象的,那麼這個類就必須被聲明爲抽象的。對象

<?php
abstract class AbstractClass
{
 // 強制要求子類定義這些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

Trait

傳統繼承增長了水平特性的組合,避免傳統多繼承和 Mixin 類相關典型問題。優先級:當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。繼承

<?php
trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
}

class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
}

class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
}

多個 trait

經過逗號分隔,在 use 聲明列出多個 trait,能夠都插入到一個類中。ip

<?php
trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World';
    }
}

class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
        echo '!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();

解決trait衝突

若是兩個 trait 都插入了一個同名的方法,若是沒有明確解決衝突將會產生一個致命錯誤。
須要使用 insteadof 操做符來明確指定使用衝突方法中的哪個。as 操做符能夠將其中一個衝突的方法以另外一個名稱來引入。
示例:定義了使用 trait B 中的 smallTalk 以及 trait A 中的 bigTalk,用了 as 操做符來定義了 talk 來做爲 B 的 bigTalk 的別名。

<?php
trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}

修改訪問控制權限

使用as

<?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}

// 修改 sayHello 的訪問控制
class MyClass1 {
    use HelloWorld { sayHello as protected; }
}

// 給方法一個改變了訪問控制的別名
// 原版 sayHello 的訪問控制則沒有發生變化
class MyClass2 {
    use HelloWorld { sayHello as private myPrivateHello; }
}
?>

其餘

其它 trait 也可以使用 trait。
trait 支持抽象方法的使用。
Trait 一樣能夠定義屬性。

匿名類

匿名類被嵌套進普通 Class 後,不能訪問這個外部類(Outer class)的 private(私有)、protected(受保護)方法或者屬性。 爲了訪問外部類(Outer class)protected 屬性或方法,匿名類能夠 extend(擴展)此外部類。 爲了使用外部類(Outer class)的 private 屬性,必須經過構造器傳進來:

<?php

class Outer
{
    private $prop = 1;
    protected $prop2 = 2;

    protected function func1()
    {
        return 3;
    }

    public function func2()
    {
        return new class($this->prop) extends Outer {
            private $prop3;

            public function __construct($prop)
            {
                $this->prop3 = $prop;
            }

            public function func3()
            {
                return $this->prop2 + $this->prop3 + $this->func1();
            }
        };
    }
}

echo (new Outer)->func2()->func3();

魔術方法

不可訪問屬性、不可訪問方法:未定義或不可見的類屬性或方法
在給不可訪問屬性賦值時,__set() 會被調用。
讀取不可訪問屬性的值時,__get() 會被調用。
當對不可訪問屬性調用 isset() 或 empty() 時,__isset() 會被調用。
當對不可訪問屬性調用 unset() 時,__unset() 會被調用。
在對象中調用一個不可訪問方法時,__call() 會被調用。
在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。
serialize() 函數會檢查類中是否存在一個魔術方法 __sleep()。若是存在,該方法會先被調用,而後才執行序列化操做。此功能能夠用於清理對象,並返回一個包含對象中全部應被序列化的變量名稱的數組。
unserialize() 會檢查是否存在一個 __wakeup() 方法。若是存在,則會先調用 __wakeup 方法,預先準備對象須要的資源。

public void __set ( string $name , mixed $value )
public mixed __get ( string $name )
public bool __isset ( string $name )
public void __unset ( string $name )
public mixed __call ( string $name , array $arguments )
public static mixed __callStatic ( string $name , array $arguments )
__construct(), __destruct(), __sleep(), __wakeup(), __toString(), __invoke(),__set_state(), __clone() , __debugInfo()

示例:

<?php
class PropertyTest {
     /**  被重載的數據保存在此  */
    private $data = array();

 
     /**  重載不能被用在已經定義的屬性  */
    public $declared = 1;

     /**  只有從類外部訪問這個屬性時,重載纔會發生 */
    private $hidden = 2;

    public function __set($name, $value) 
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name) 
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    /**  PHP 5.1.0以後版本 */
    public function __isset($name) 
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    /**  PHP 5.1.0以後版本 */
    public function __unset($name) 
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  非魔術方法  */
    public function getHidden() 
    {
        return $this->hidden;
    }
}

call示例:arguments是一個數組

<?php
class MethodTest 
{
    public function __call($name, $arguments) 
    {
        // 注意: $name 的值區分大小寫
        var_dump($arguments);
    }

    /**  PHP 5.3.0以後版本  */
    public static function __callStatic($name, $arguments) 
    {
        // 注意: $name 的值區分大小寫
        var_dump($arguments);
    }
}

$obj = new MethodTest;
$obj->runTest('in object context','fyfy');

MethodTest::runTest('in static context');  // PHP 5.3.0以後版本
?>

//輸出相似
/*
array(2) {
  [0] =>
  string(17) "in object context"
  [1] =>
  string(4) "fyfy"
}
array(1) {
  [0] =>
  string(17) "in static context"
}

*/

遍歷對象

默認狀況下,全部可見屬性都將被用於遍歷。

<?php
class MyClass
{
    public $var1 = 'value 1';
    public $var2 = 'value 2';
    public $var3 = 'value 3';

    protected $protected = 'protected var';
    private   $private   = 'private var';

    function iterateVisible() {
       echo "MyClass::iterateVisible:\n";
       foreach($this as $key => $value) {
           print "$key => $value\n";
       }
    }
}

$class = new MyClass();

foreach($class as $key => $value) {
    print "$key => $value\n";
}
echo "\n";

$class->iterateVisible();
?>

對象複製

clone 關鍵字,淺複製(shallow copy)。全部的引用屬性 仍然會是一個指向原來的變量的引用。當複製完成時,若是定義了 __clone() 方法,則新建立的對象(複製生成的對象)中的 __clone() 方法會被調用,可用於修改屬性的值(若是有必要的話)。
示例:關於淺複製

<?php
class subclass{
  public $var1='subclass default';
}

class MyClass
{
    public $var1 = 'myclass default';
    public $object;

    function __construct(){
      $this->object=new subclass();
    }
}

$object1 = new MyClass();
$object2 = clone $object1;
$object1->object->var1='object1 change';
$object1->var1='object1 change';

print_r($object1);
print_r($object2);
?>

輸出結果:

MyClass Object
(
    [var1] => object1 change
    [object] => subclass Object
        (
            [var1] => object1 change
        )

)
MyClass Object
(
    [var1] => myclass default
    [object] => subclass Object
        (
            [var1] => object1 change
        )

對象比較

==:兩個對象的屬性和屬性值 都相等,並且兩個對象是同一個類的實例,那麼這兩個對象變量相等。 ===:必須是同一個對象。

相關文章
相關標籤/搜索