国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

php易錯筆記-類與對象,命名空間

MartinHan / 1597人閱讀

摘要:類與對象基本概念如果在之后跟著的是一個包含有類名的字符串,則該類的一個實例被創建。如果該類屬于一個名字空間,則必須使用其完整名稱。如果一個類被聲明為,則不能被繼承。命名空間通過關鍵字來聲明。

類與對象 基本概念
new:如果在 new 之后跟著的是一個包含有類名的字符串,則該類的一個實例被創建。如果該類屬于一個名字空間,則必須使用其完整名稱

Example #3 創建一個實例


在類定義內部,可以用 new selfnew parent 創建新對象。

PHP 5.3.0 引進了兩個新方法來創建一個對象的實例:


自 PHP 5.5 起,關鍵詞 class 也可用于類名的解析:ClassName::class

當把一個對象已經創建的實例賦給一個新變量時,新變量會訪問同一個實例,就和用該對象賦值一樣。此行為和給函數傳遞入實例時一樣。可以用克隆給一個已創建的對象建立一個新實例。

foo = "qux";
var_dump( $objectVar );
var_dump( $reference );
var_dump( $assignment );
var_dump( $cloneObj );

echo "--------------------", PHP_EOL;

$objectVar = null;
var_dump($objectVar);
var_dump($reference);
var_dump($assignment);
var_dump($cloneObj);

/*
Result:

object(Object)#1 (1) {
  ["foo"]=>
  string(3) "qux"
}
object(Object)#1 (1) {
  ["foo"]=>
  string(3) "qux"
}
object(Object)#1 (1) {
  ["foo"]=>
  string(3) "qux"
}
object(Object)#2 (1) {
  ["foo"]=>
  string(3) "bar"
}
--------------------
NULL
NULL
object(Object)#1 (1) {
  ["foo"]=>
  string(3) "qux"
}
object(Object)#2 (1) {
  ["foo"]=>
  string(3) "bar"
}
*/
類的自動加載

spl_autoload_register() 函數可以注冊任意數量的自動加載器,當使用尚未被定義的類(class)和接口(interface)時自動去加載。通過注冊自動加載器,腳本引擎在 PHP 出錯失敗前有了最后一個機會加載所需的類。

盡管 __autoload() 函數也能自動加載類和接口,但更建議使用 spl_autoload_register() 函數。 spl_autoload_register() 提供了一種更加靈活的方式來實現類的自動加載(同一個應用中,可以支持任意數量的加載器,比如第三方庫中的)。因此,不再建議使用 __autoload() 函數,在以后的版本中它可能被棄用。

Example #1 自動加載示例

本例嘗試分別從 MyClass1.php 和 MyClass2.php 文件中加載 MyClass1 和 MyClass2 類。


構造函數和析構函數
Note: 如果子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,需要在子類的構造函數中調用 parent::__construct()。如果子類沒有定義構造函數則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。

和構造函數一樣,父類的析構函數不會被引擎暗中調用。要執行父類的析構函數,必須在子類的析構函數體中顯式調用 parent::__destruct()。此外也和構造函數一樣,子類如果自己沒有定義析構函數則會繼承父類的。

析構函數即使在使用 exit() 終止腳本運行時也會被調用。在析構函數中調用 exit() 將會中止其余關閉操作的運行。

訪問控制(可見性)

類屬性必須定義為公有受保護私有之一。如果用 var 定義,則被視為公有。

類中的方法可以被定義為公有私有受保護。如果沒有設置這些關鍵字,則該方法默認為公有

同一個類的對象即使不是同一個實例也可以互相訪問對方的私有與受保護成員。這是由于在這些對象的內部具體實現的細節都是已知的。

Example #3 訪問同一個對象類型的私有成員

foo = $foo;
    }

    private function bar()
    {
        echo "Accessed the private method.";
    }

    public function baz(Test $other)
    {
        // We can change the private property:
        $other->foo = "hello";
        var_dump($other->foo);

        // We can also call the private method:
        $other->bar();
    }
}

$test = new Test("test");

$test->baz(new Test("other"));

//string(5) "hello"
//Accessed the private method.
?>

繼承和訪問控制:

overridden(); 
    } 
    private function overridden() { 
        echo "base"; 
    } 
} 

class child extends base { 
    private function overridden() { 
        echo "child"; 
    } 
} 

$test = new child(); 
$test->inherited(); 
?> 

Output will be "base". 

If you want the inherited methods to use overridden functionality in extended classes but public sounds too loose, use protected. That"s what it is for:) 

A sample that works as intended: 

overridden(); 
    } 
    protected function overridden() { 
        echo "base"; 
    } 
} 

class child extends base { 
    protected function overridden() { 
        echo "child"; 
    } 
} 

$test = new child(); 
$test->inherited(); 
?> 
Output will be "child".
范圍解析操作符 (::)

范圍解析操作符(也可稱作 Paamayim Nekudotayim)或者更簡單地說是一對冒號,可以用于訪問靜態成員類常量,還可以用于覆蓋類中的屬性和方法

訪問靜態變量,靜態方法,常量:


Example #3 調用父類的方法

myFunc();
?>
Static(靜態)關鍵字
用 static 關鍵字來定義靜態方法屬性。static 也可用于定義靜態變量以及后期靜態綁定

聲明類屬性或方法為靜態,就可以不實例化類而直接訪問。靜態屬性不能通過一個類已實例化的對象來訪問(但靜態方法可以)

抽象類

繼承一個抽象類的時候:
1.子類必須定義父類中的所有抽象方法
2.這些方法的訪問控制必須和父類中一樣(或者更為寬松)。例如某個抽象方法被聲明為受保護的,那么子類中實現的方法就應該聲明為受保護的或者公有的,而不能定義為私有的;
3.方法的調用方式必須匹配,即類型和所需參數數量必須一致。例如,子類定義了一個可選參數,而父類抽象方法的聲明里沒有,則兩者的聲明并無沖突。 這也適用于 PHP 5.4 起的構造函數。在 PHP 5.4 之前的構造函數聲明可以不一樣的;

對象接口

接口中定義的所有方法都必須是公有,這是接口的特性。
實現類必須實現接口中定義的所有方法
可以實現多個接口,用逗號來分隔多個接口的名稱。
實現多個接口時,接口中的方法不能有重名
類要實現接口,必須使用和接口中所定義的方法完全一致的方式
接口中也可以定義常量。接口常量和類常量的使用完全相同,但是不能被子類或子接口所覆蓋

Trait

自 PHP 5.4.0 起,PHP 實現了一種代碼復用的方法,稱為 trait

Trait 是為類似 PHP 的單繼承語言而準備的一種代碼復用機制。Trait 為了減少單繼承語言的限制,使開發人員能夠自由地在不同層次結構內獨立的類中復用 method。Trait 和 Class 組合的語義定義了一種減少復雜性的方式,避免傳統多繼承和 Mixin 類相關典型問題。

Trait 和 Class 相似,但僅僅旨在用細粒度和一致的方式來組合功能。 無法通過 trait 自身來實例化。它為傳統繼承增加了水平特性的組合;也就是說,應用的幾個 Class 之間不需要繼承。

優先級:從基類繼承的成員會被 trait 插入的成員所覆蓋。優先順序是來自當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。

sayHello();//Hello World!
?>

多個 trait:通過逗號分隔,在 use 聲明列出多個 trait,可以都插入到一個類中。

沖突的解決:為了解決多個 trait 在同一個類中的命名沖突,需要使用 insteadof 操作符來明確指定使用沖突方法中的哪一個


修改方法的訪問控制使用 as 語法還可以用來調整方法的訪問控制。


trait 來組成 trait在 trait 定義時通過使用一個或多個 trait,能夠組合其它 trait 中的部分或全部成員。

sayHello();
$o->sayWorld();
?>

Trait 的抽象成員為了對使用的類施加強制要求,trait 支持抽象方法的使用。

getWorld();
    }
    abstract public function getWorld();
}

class MyHelloWorld {
    private $world;
    use Hello;
    public function getWorld() {
        return $this->world;
    }
    public function setWorld($val) {
        $this->world = $val;
    }
}
?>

Trait 的靜態成員Traits 可以被靜態成員靜態方法定義。



Example using trait:

屬性Trait 同樣可以定義屬性。
Trait 定義了一個屬性后,類就不能定義同樣名稱的屬性,否則會產生 fatal error。 有種情況例外:屬性是兼容的(同樣的訪問可見度、初始默認值)。 在 PHP 7.0 之前,屬性是兼容的,則會有 E_STRICT 的提醒。

Example #12 解決沖突


重載(術語濫用)

PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法。我們是通過魔術方法(magic methods)來實現的。

當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。本節后面將使用"不可訪問屬性(inaccessible properties)"和"不可訪問方法(inaccessible methods)"來稱呼這些未定義或不可見的類屬性或方法。

This is a misuse of the term overloading. This article should call this technique "interpreter hooks".

參加魔術方法php超全局變量,魔術常量,魔術方法

Note:
因為 PHP 處理賦值運算的方式,__set() 的返回值將被忽略。類似的, 在下面這樣的鏈式賦值中,__get() 不會被調用: $a = $obj->b = 8;

Note:
在除 isset() 外的其它語言結構中無法使用重載的屬性,這意味著當對一個重載的屬性使用 empty() 時,重載魔術方法將不會被調用。
為避開此限制,必須將重載屬性賦值到本地變量再使用 empty()

遍歷對象

1.用 foreach 語句。默認情況下,所有可見屬性都將被用于遍歷。

public[] = $i;
        }
    }
    function __destruct()
    {
        foreach ($this as $key => list($a, $b, $c)) {
            print "$key => [$a, $b, $c]
";
        }
    }
} as $key => list($a, $b, $c)) {
    print "$key => [$a, $b, $c]
";
}
echo "
";

//Result:
/*
public => [0, 1, 2]
public => [0, 1, 2]
protected => [3, 4, 5]
private => [6, 7, 8]
 */

2.實現 Iterator 接口。可以讓對象自行決定如何遍歷以及每次遍歷時那些值可用。

var = $array;
        }
    }

    public function rewind() {
        echo "rewinding
";
        reset($this->var);
    }

    public function current() {
        $var = current($this->var);
        echo "current: $var
";
        return $var;
    }

    public function key() {
        $var = key($this->var);
        echo "key: $var
";
        return $var;
    }

    public function next() {
        $var = next($this->var);
        echo "next: $var
";
        return $var;
    }

    public function valid() {
        $var = $this->current() !== false;
        echo "valid: {$var}
";
        return $var;
    }
}

$values = array(1,2,3);
$it = new MyIterator($values);

foreach ($it as $a => $b) {
    print "$a: $b
";
}
?>

可以用 IteratorAggregate 接口以替代實現所有的 Iterator 方法。IteratorAggregate 只需要實現一個方法 IteratorAggregate::getIterator()其應返回一個實現了 Iterator 的類的實例

Example #3 通過實現 IteratorAggregate 來遍歷對象

items);
    }

    public function add($value) {
        $this->items[$this->count++] = $value;
    }
}

$coll = new MyCollection();
$coll->add("value 1");
$coll->add("value 2");
$coll->add("value 3");

foreach ($coll as $key => $val) {
    echo "key/value: [$key -> $val]

";
}
?>
PHP 5.5 及以后版本的用戶也可參考生成器,其提供了另一方法來定義 Iterators。
魔術方法

參見php超全局變量,魔術常量,魔術方法。

final

如果父類中的方法被聲明為 final,則子類無法覆蓋該方法。如果一個類被聲明為 final,則不能被繼承

屬性不能被定義為 final,只有類和方法才能被定義為 final。可以使用 const 定義為常量來代替。
對象復制(clone)

對象復制可以通過 clone 關鍵字來完成(如果可能,這將調用對象的 __clone() 方法)。對象中的 __clone() 方法不能被直接調用。

當對象被復制后,PHP 5 會對對象的所有屬性執行一個淺復制shallow copy)。所有的引用屬性 仍然會是一個指向原來的變量的引用
對象比較

==:如果兩個對象的屬性和屬性值都相等,而且兩個對象是同一個類的實例,那么這兩個對象變量相等。
===:這兩個對象變量一定要指向某個類的同一個實例(即同一個對象,但不需要引用賦值)。

flag = $flag; }
}

class OtherFlag
{
    public $flag;
    function __construct($flag = true) { $this->flag = $flag; }
}

$o = new Flag;
$p = new Flag;
$q = $o;
$r = new OtherFlag;
$s = new Flag(false);

echo "Two instances of the same class
";
compareObjects($o, $p);

echo "
Two references to the same instance
";
compareObjects($o, $q);

echo "
Instances of two different classes
";
compareObjects($o, $r);

echo "Two instances of the same class
";
compareObjects($o, $s);

//Result:
/*
Two instances of the same class
o1 == o2 : true
o1 === o2 : false

Two references to the same instance
o1 == o2 : true
o1 === o2 : true

Instances of two different classes
o1 == o2 : false
o1 === o2 : false

Two instances of the same class
o1 == o2 : false
o1 === o2 : false
 */
?>
后期靜態綁定

后期靜態綁定static:: 不再被解析為定義當前方法所在的類,而是在實際運行時計算的。也可以稱之為“靜態綁定”,因為它可以用于(但不限于)靜態方法的調用。

Example #2 static:: 簡單用法


Finally we can implement some ActiveRecord methods:

 

Output: "Product"
對象和引用
Notes on reference:
A reference is not a pointer. However, an object handle IS a pointer. Example:

命名空間
定義命名空間

雖然任意合法的PHP代碼都可以包含在命名空間中,但只有以下類型的代碼受命名空間的影響,它們是:(包括抽象類traits)、接口函數常量

命名空間通過關鍵字 namespace 來聲明。如果一個文件中包含命名空間,它必須在其它所有代碼之前聲明命名空間,除了一個以外:declare關鍵字

define() will define constants exactly as specified:

Regarding constants defined with define() inside namespaces...

define() will define constants exactly as specified.  So, if you want to define a constant in a namespace, you will need to specify the namespace in your call to define(), even if you"re calling define() from within a namespace.  The following examples will make it clear.

The following code will define the constant "MESSAGE" in the global namespace (i.e. "MESSAGE").



The following code will define two constants in the "test" namespace.


在同一個文件中定義多個命名空間(不建議)

也可以在同一個文件中定義多個命名空間。在同一個文件中定義多個命名空間有兩種語法形式:簡單組合語法大括號語法

Example #4 定義多個命名空間和不包含在命名空間中的代碼


使用命名空間:基礎

(PHP 5 >= 5.3.0, PHP 7)
在討論如何使用命名空間之前,必須了解 PHP 是如何知道要使用哪一個命名空間中的元素的。可以將 PHP 命名空間與文件系統作一個簡單的類比。在文件系統中訪問一個文件有三種方式:

相對文件名形式foo.txt。它會被解析為 currentdirectory/foo.txt,其中 currentdirectory 表示當前目錄。因此如果當前目錄是 /home/foo,則該文件名被解析為/home/foo/foo.txt

相對路徑名形式subdirectory/foo.txt。它會被解析為 currentdirectory/subdirectory/foo.txt

絕對路徑名形式/main/foo.txt。它會被解析為/main/foo.txt

PHP 命名空間中的元素使用同樣的原理。例如,類名可以通過三種方式引用:

非限定名稱,或不包含前綴的類名稱,例如 $a=new foo(); 或 foo::staticmethod();。如果當前命名空間是 currentnamespacefoo 將被解析為 currentnamespacefoo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,則 foo 會被解析為foo。 警告:如果命名空間中的函數或常量未定義,則該非限定的函數名稱或常量名稱會被解析為全局函數名稱或常量名稱。詳情參見 使用命名空間:后備全局函數名稱/常量名稱。

限定名稱,或包含前綴的名稱,例如 $a = new subnamespacefoo(); 或 subnamespacefoo::staticmethod();。如果當前的命名空間是 currentnamespace,則 foo 會被解析為 currentnamespacesubnamespacefoo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,foo 會被解析為subnamespacefoo

完全限定名稱,或包含了全局前綴操作符的名稱,例如, $a = new currentnamespacefoo(); 或 currentnamespacefoo::staticmethod();。在這種情況下,foo 總是被解析為代碼中的文字名(literal name)currentnamespacefoo

下面是一個使用這三種方式的實例:

file1.php


file2.php


注意訪問任意全局類、函數或常量,都可以使用完全限定名稱,例如 strlen()ExceptionINI_ALL

Example #1 在命名空間內部訪問全局類、函數和常量


命名空間和動態語言特征

php.php


test.php


namespace關鍵字和__NAMESPACE__常量

常量__NAMESPACE__的值是包含當前命名空間名稱的字符串。在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。
關鍵字 namespace 可用來顯式訪問當前命名空間或子命名空間中的元素。它等價于類中的 self 操作符。


使用命名空間:別名/導入

別名是通過操作符 use 來實現的:所有支持命名空間的PHP版本支持三種別名或導入方式:為類名稱使用別名為接口使用別名為命名空間名稱使用別名

PHP 5.6開始允許導入函數常量或者為它們設置別名。

Example #1 使用use操作符導入/使用別名


對命名空間中的名稱(包含命名空間分隔符的完全限定名稱如 FooBar以及相對的不包含命名空間分隔符的全局名稱如 FooBar)來說,前導的反斜杠是不必要的也不推薦的,因為導入的名稱必須是完全限定的,不會根據當前的命名空間作相對解析。

導入操作只影響非限定名稱和限定名稱。完全限定名稱由于是確定的,故不受導入的影響。

全局空間

如果沒有定義任何命名空間,所有的類與函數的定義都是在全局空間,與 PHP 引入命名空間概念前一樣。在名稱前加上前綴 表示該名稱是全局空間中的名稱,即使該名稱位于其它的命名空間中時也是如此。

使用命名空間:后備全局函數/常量

在一個命名空間中,當 PHP 遇到一個非限定的類、函數或常量名稱時,它使用不同的優先策略來解析該名稱。類名稱總是解析到當前命名空間中的名稱。因此在訪問系統內部或不包含在命名空間中的類名稱時,必須使用完全限定名稱,例如:

getMessage();
} finally {
    echo PHP_EOL, "finally do";
}

//Result
/*
My Exception
finally do
 */
名稱解析規則

在說明名稱解析規則之前,我們先看一些重要的定義:

命名空間名稱定義

非限定名稱Unqualified name

名稱中不包含命名空間分隔符的標識符,例如 Foo

限定名稱Qualified name

名稱中含有命名空間分隔符的標識符,例如 FooBar

完全限定名稱Fully qualified name

名稱中包含命名空間分隔符,并以命名空間分隔符開始的標識符,例如 FooBarnamespaceFoo 也是一個完全限定名稱。

名稱解析遵循下列規則:

對完全限定名稱的函數,類和常量的調用在編譯時解析。例如 new AB 解析為類 AB

所有的非限定名稱和限定名稱(非完全限定名稱)根據當前的導入規則在編譯時進行轉換。例如,如果命名空間 ABC 被導入為 C,那么對 CDe() 的調用就會被轉換為 ABCDe()

在命名空間內部,所有的沒有根據導入規則轉換的限定名稱均會在其前面加上當前的命名空間名稱。例如,在命名空間 AB 內部調用 CDe(),則 CDe() 會被轉換為 ABCDe()

非限定類名根據當前的導入規則在編譯時轉換(用全名代替短的導入名稱)。例如,如果命名空間 ABC 導入為C,則 new C() 被轉換為 new ABC()

在命名空間內部(例如AB),對非限定名稱的函數調用是在運行時解析的。例如對函數 foo()
的調用是這樣解析的:

在當前命名空間中查找名為 ABfoo() 的函數

嘗試查找并調用 全局(global) 空間中的函數 foo()

在命名空間(例如AB)內部對非限定名稱或限定名稱類(非完全限定名稱)的調用是在運行時解析的。下面是調用 new C()new DE() 的解析過程: new C()的解析:

在當前命名空間中查找ABC類。

嘗試自動裝載類ABC

new DE()的解析:

在類名稱前面加上當前命名空間名稱變成:ABDE,然后查找該類。

嘗試自動裝載類 ABDE

為了引用全局命名空間中的全局類,必須使用完全限定名稱 new C()

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28191.html

相關文章

  • php易錯筆記-類型

    摘要:非法下標類型會產生一個級別錯誤。用負數下標寫入字符串時會產生一個級別錯誤,用負數下標讀取字符串時返回空字符串。浮點數也會被轉換為整型,意味著其小數部分會被舍去。 Boolean 當轉換為 boolean 時,以下值被認為是 FALSE:布爾值 FALSE 本身整型值 0(零)浮點型值 0.0(零)空字符串,以及字符串 0不包括任何元素的數組[]特殊類型 NULL(包括尚未賦值的變量)從...

    tinyq 評論0 收藏0
  • php.類與對象

    摘要:接口可以使用常量,叫接口常量,和類的常量使用方法相同類可以同時繼承多個接口使用接口常量抽象類不能被實例化。繼承抽象類,子類必須實現父類中所有的抽象方法。 訪問控制 屬性和方法的訪問控制(可見標識):public 任何地方private 類自身protected 類自身,自子類及自父類 this this 可以理解為這個類的一個實例 self self 代表類本身 __construc...

    scq000 評論0 收藏0
  • php易錯筆記-流程控制,函數

    摘要:的語法和其它流程控制結構相似部分允許設定代碼段的行為。返回值在失敗時返回并且發出警告。當一個函數是有條件被定義時,必須在調用函數之前定義。有條件的函數不能在此處調用函數,因為它還不存在,但可以調用函數。 流程控制 PHP 提供了一些流程控制的替代語法,包括 if,while,for,foreach 和 switch。替代語法的基本形式是把左花括號({)換成冒號(:),把右花括號(})分...

    mrcode 評論0 收藏0
  • PHP 手冊閱讀筆記 - 語言參考篇

    摘要:最近計劃把手冊,認真的先過一遍。語言參考類型新認知強制轉換類型用。后期靜態綁定從這里開始語言參考生成器新認知生成器汗水的核心是關鍵字。語言參考預定義變量超全局變量前一個錯誤信息原始數據以上 showImg(https://segmentfault.com/img/remote/1460000010147451); 最近計劃把 PHP手冊,認真的先過一遍。記錄一些以前不知道,不明確的知識...

    Developer 評論0 收藏0
  • PHP面試常考內容之面向對象(3)

    摘要:面試專欄正式起更,每周一三五更新,提供最好最優質的面試內容。繼上一篇面試常考內容之面向對象發表后,今天更新面向對象的最后一篇。面向對象的主要特征為封裝繼承多態。為了提高內聚性減少引起變化,單一原則是低耦合高內聚的面向原則上的引申。 PHP面試專欄正式起更,每周一、三、五更新,提供最好最優質的PHP面試內容。繼上一篇PHP面試常考內容之面向對象(2)發表后,今天更新面向對象的最后一篇(3...

    xfee 評論0 收藏0

發表評論

0條評論

MartinHan

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<