認識 PHP 物件導向(二)

前言

本文為〈PHP OO 基礎教學〉一文的學習筆記。

類別繼承

使用 extends 關鍵字,讓類別繼承其他類別的方法和屬性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

public function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}
}

$new_obj = new NewClass;
echo $new_obj->newMethod();
echo $new_obj->getProperty();

結果:

1
2
3
4
The class "MyClass" was initiated!
From a new method in NewClass.
I'm a class property!
The class "MyClass" was destroyed.

類別繼承覆寫

可以在新類別重新定義更改繼承的屬性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

public function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function __construct()
{
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}
}

$new_obj = new NewClass;
echo $new_obj->newMethod();
echo $new_obj->getProperty();

結果:

1
2
3
4
A new constructor in NewClass.
From a new method in NewClass.
I'm a class property!
The class "MyClass" was destroyed.

呼叫父類別方法

使用「::」範圍解析運算子,在沒有宣告任何實體的情況下存取類別中的函式或基本類別中的函式和變數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

public function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function __construct()
{
parent::__construct();
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}
}

$new_obj = new NewClass;
echo $new_obj->newMethod();
echo $new_obj->getProperty();

結果:

1
2
3
4
5
The class "MyClass" was initiated!
A new constructor in NewClass.
From a new method in NewClass.
I'm a class property!
The class "MyClass" was destroyed.

定義可視性

當一個變數或方法的可視性被宣告為 protected,該變數或方法只能在該類別以及子類別的內部存取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

protected function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function __construct()
{
parent::__construct();
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}
}

結果:

1
2
3
4
The class "MyClass" was initiated!
A new constructor in NewClass.

Fatal error: Uncaught Error: Call to protected method MyClass::getProperty() from context '' in C:\Users\William\Xampp\htdocs\projects\php\oo.php:49

子類別可以調用父類別可視度為 protected 的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

protected function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function __construct()
{
parent::__construct();
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}

public function callProtected()
{
return $this->getProperty();
}
}

$new_obj = new NewClass;
echo $new_obj->callProtected();

結果:

1
2
3
4
The class "MyClass" was initiated!
A new constructor in NewClass.
I'm a class property!
The class "MyClass" was destroyed.

當一個變數或方法的可視性被宣告為 private,該變數或方法只能在該類別的內部存取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class MyClass
{
public $prop = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

private function getProperty()
{
return $this->prop . "<br>";
}
}

class NewClass extends MyClass
{
public function __construct()
{
parent::__construct();
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}

public function callProtected()
{
return $this->getProperty();
}
}

$new_obj = new NewClass;
echo $new_obj->callProtected();

結果:

1
2
3
4
5
The class "MyClass" was initiated!
A new constructor in NewClass.


Fatal error: Uncaught Error: Call to private method MyClass::getProperty() from context 'NewClass' in C:\Users\William\Xampp\htdocs\projects\php\oo.php:49

當一個變數或方法的可視性被宣告為 static,該變數或方法可以在類別還沒有被實例化就被調用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class MyClass
{
public $prop = "I'm a class property!";

public static $count = 0;

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method.<br />";
return $this->getProperty();
}

public function setProperty($new)
{
$this->prop = $new;
}

private function getProperty()
{
return $this->prop . "<br>";
}

public static function plusOne()
{
return "The count is " . ++self::$count . ".<br />";
}
}

class NewClass extends MyClass
{
public function __construct()
{
parent::__construct();
echo "A new constructor in " . __CLASS__ . ".<br />";
}

public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}

public function callProtected()
{
return $this->getProperty();
}
}

do {
echo MyClass::plusOne();
} while ( MyClass::$count < 10 );
  • self 是指向類本身,也就是 self 是不指向任何已經產生實體的物件,一般 self 是用來指向類中的靜態變數。

結果:

1
2
3
4
5
6
7
8
9
10
The count is 1.
The count is 2.
The count is 3.
The count is 4.
The count is 5.
The count is 6.
The count is 7.
The count is 8.
The count is 9.
The count is 10.