Polymorphism
)按字面的意思就是「多種狀態」abstract
abstract class MyAbsClass {
abstract public function func();
}
複製代碼
<?php
abstract class MyAbsClass {
abstract public function func();
}
class ChildClass extends MyAbsClass {
// 這樣寫會報錯, 由於沒有實現抽象類中定義的方法
}
複製代碼
<?php
abstract class MyAbsClass {
abstract public function func();
}
class ChildClass extends MyAbsClass {
public function func() {
// 即使什麼都沒有寫, 也沒有關係...
}
}
複製代碼
<?php
abstract class MyAbsClass {
abstract public function func();
}
abstract class ChildClass extends MyAbsClass {
// 什麼都沒寫, 也不會報錯...
}
複製代碼
abstract class MyAbsClass {
public function func(); // 會報錯, 由於沒有abstract關鍵字
}
複製代碼
class MyAbsClass // 會報錯, 由於沒有abstract關鍵字 {
abstract public function func();
}
複製代碼
<?php
abstract class MyAbsClass {
public $name = '張三';
public $age;
public function test() {
echo 'hello';
}
abstract public function func();
}
複製代碼
final public static function
php
使用接口(interface),能夠指定某個類必須實現哪些方法,但不須要定義這些方法的具體內容。編程
接口中也能夠定義常量。函數
接口實現關鍵字implementsthis
<?php
interface MyInterface {
const NUM = 123;
public function func();
public function test();
}
class MyClass implements MyInterface {
public function func() {
}
public function test() {
echo 'hello';
}
}
複製代碼
<?php
interface MyInterface {
const NUM = 123;
public function func();
public function test() {
echo "test"; // 會報錯, 不能有具體方法
};
}
複製代碼
<?php
interface MyInterface {
const NUM = 123;
public function func();
public function test();
}
class MyClass implements MyInterface {
public function func() {
}
// 報錯, 由於沒有實現test()
}
複製代碼
<?php
interface MyInterface {
const NUM = 123;
public function func();
public function test();
}
abstract class MyClass implements MyInterface {
// 沒有實現接口的方法, 也不會報錯
}
class Demo extends MyClass {
public function func() {
// 必須實現, 不然報錯
}
public function test() {
// 必須實現, 不然報錯
}
}
複製代碼
<?php
interface A {
public function aaa();
}
interface B extends A {
public function bbb();
}
class C implements A {
public function bbb() {
//
}
public function aaa() {
}
}
複製代碼
<?php
interface A {
public function aaa();
}
interface B {
public function bbb();
}
class C implements A, B {
public function bbb() {
// 都得實現, 否則報錯
}
public function aaa() {
// 都得實現, 否則報錯
}
}
複製代碼
<?php
interface A {
public function aaa();
}
interface B {
public function bbb();
}
class C {
public function bbb() {
}
public function aaa() {
}
}
class D extends C implements A, B {
// 類D繼承C, C實現了A和B
}
複製代碼
抽象類有普通的方法,接口沒有spa
抽象類能夠有本身的成員屬性和方法,接口只能有public 常量。操作系統
抽象類無關緊要構造方法,接口沒有構造方法code
抽象類單繼承,接口多重繼承cdn
instanceof
用於肯定一個PHP變量是否屬於某一類class的實例<?php
class A {
}
class B {
}
$a = new A();
var_dump($a instanceof A); // true
var_dump($a instanceof B); // false
複製代碼
instanceof
也可用來肯定一個變量是否是繼承自某一父類的子類的實例<?php
class A extends B {
}
class B {
}
$a = new A();
var_dump($a instanceof A); // true
var_dump($a instanceof B); // true
複製代碼
instanceof
也可用於肯定一個變量是否是實現了某個接口的對象的實例<?php
class A implements B {
}
interface B {
}
$a = new A();
var_dump($a instanceof A); // true
var_dump($a instanceof B); // true
複製代碼
<?php
class A {
}
class B {
}
$a = new A();
$b = new B();
function test(A $n) {
echo "ok";
}
test($a); // 輸出ok
test($b); // 報錯, 由於$b是B的實例, 不是A的實例
複製代碼
<?php
class A {
public function aaa(B $n) {
}
}
class B {
}
class C extends B {
public $a = '123';
}
class D extends A {
}
$a = new A();
$c = new C();
$a->aaa($c);
複製代碼
須要的類在不一樣文件
)__autoload()
函數也能自動加載類和接口spl_autoload_register()
函數能夠註冊任意數量的自動加載器,spl_autoload_register()
函數__autoload()
函數,在之後的版本中它可能被棄用
C:\Users\Administrator\Desktop\imooc\a.class.php
對象
<?php
class A extends B {
// 會報錯, 由於找不到B
}
複製代碼
C:\Users\Administrator\Desktop\imooc\b.class.php
blog
<?php
class B {
}
複製代碼
引入便可
<?php
include 'b.class.php'; // 引入便可
class A extends B {
// 會報錯, 由於找不到B
}
複製代碼
使用自動加載
<?php
function myloader() {
echo '被執行了...';
include 'b.class.php';
}
spl_autoload_register('myloader'); // 執行myloader
class A extends B {
}
複製代碼
使用靜態方法
<?php
class Loader {
public static function myloader() {
echo '被執行了...';
include 'b.class.php';
}
}
spl_autoload_register(['Loader', 'myloader']); // 執行myloader
class A extends B {
// 不會報錯
}
複製代碼
也能夠作成構造方法
<?php
class Loader {
public function __construct() {
spl_autoload_register([$this, 'myloader']);
}
public function myloader() {
echo '被執行了...';
include 'b.class.php';
}
}
$obj = new Loader();
class A extends B {
}
複製代碼
接口同理...
編程中常見的兩類問題
定義命名空間
namespace
來聲明。namespace Project1;
// 代碼...
namespace Project2{
// 代碼...
}
複製代碼
<?php
namespace MySapce {
function test()
{
echo 'test1';
}
test(); // 不會報錯
}
namespace MySapce2 {
function test()
{
echo 'test2';
}
test(); // 不會報錯
}
複製代碼
<?php
namespace myspace;
function time() {
echo 'hello';
}
time(); // 不會報錯, 輸出hello
複製代碼
<?php
namespace myspace1;
function time() {
echo 'hello1';
}
time(); // 不會報錯, 輸出hello1
namespace myspace2;
function time() {
echo 'hello2';
}
time(); // 不會報錯, 輸出hello2
複製代碼
指定命名空間
<?php
namespace myspace1;
function time() {
echo 'hello1';
}
namespace myspace2;
function time() {
echo 'hello2';
}
\myspace1\time(); // hello1
複製代碼
使用系統的time方法, \
表示全局
<?php
namespace myspace1;
function time() {
echo 'hello1';
}
namespace myspace2;
function time() {
echo 'hello2';
}
echo \time(); // 1567210241 系統函數, 返回時間戳
複製代碼
聲明單個命名空間namespace MyProject
定義子命名空間namespace MyProject\Sub\Level
;
能夠在同一個文件中定義多個命名空間
若是沒有定義任何命名空間,全部的類與函數的定義都是在全局空間,與PHP引入命名空間概念前同樣。
在名稱前加上前綴\
表示該名稱是全局空間中的名稱,即便該名稱位於其它的命名空間中時也是如此
__NAMESPACE__常量
常量__NAMESPACE__
的值是包含當前命名空間名稱的字符串
在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。
<?php
namespace hello\hello1;
var_dump(__NAMESPACE__); // hello\hello1
namespace hello\hello2;
var_dump(__NAMESPACE__); // hello\hello2
複製代碼
<?php
var_dump(__NAMESPACE__); // ""
複製代碼
非限定名稱, 徹底限定名稱, 限定名稱(絕對路徑, 相對路徑)
<?php
namespace A\B;
class MyClass {
public function __construct() {
echo '空間A\B 中的類 實例化了' . "\n";
}
}
namespace A;
class MyClass {
public function __construct() {
echo '空間A 中的類 實例化了' . "\n";
}
}
$obj = new MyClass();// 非限定名稱 就近
$obj = new \A\B\MyClass();// 徹底限定名稱 絕對路徑
$obj = new \A\MyClass();// 徹底限定名稱 絕對路徑
$obj = new B\MyClass();//限定名稱 相對路徑
複製代碼
include
不會改變當前命名空間, 可是include
以後, 可使用引入文件中的命名空間
C:\Users\Administrator\Desktop\imooc\aaa.php
<?php
namespace aaa;
function demo() {
echo 'aaa';
}
複製代碼
C:\Users\Administrator\Desktop\imooc\bbb.php
<?php
namespace bbb;
function demo() {
echo 'bbb';
}
include 'aaa.php';
demo(); // bbb
var_dump(__NAMESPACE__); // bbb
\aaa\demo(); // 可使用aaa.php的命名空間
複製代碼
動態調用函數
<?php
function demo() {
echo "demo\n";
}
demo(); // 調用demo
$a = 'demo';
$a(); // 一樣能夠調用demo
複製代碼
動態實例化對象
<?php
class A {
public function demo() {
echo "demo\n";
}
}
$a = new A();
$a->demo();
$b = "A";
$c = new $b;
$c->demo();
複製代碼
動態調用命名空間
<?php
namespace A\B;
function demo() {
echo "demo\n";
}
namespace A;
demo(); // 會報錯, 由於當前命名空間下, 沒有demo()
複製代碼
<?php
namespace A\B;
function demo() {
echo "demo\n";
}
namespace A;
\A\B\demo(); // 這就會正常了
複製代碼
<?php
namespace A\B;
function demo() {
echo "demo\n";
}
namespace A;
$a = '\A\B\demo'; // 效果同樣, 由於都是徹底限定名稱
$a = 'A\B\demo';
$a();
複製代碼
<?php
namespace A\B;
function demo() {
echo "demo\n";
}
namespace A;
$a = 'B\demo'; // 報錯, 不支持相對路徑
$a();
複製代碼