|
背景
相对于Python、Node和Ruby来说PHP算是一门容易学习和使用的语言,因为这个特点也使其成为WEB开发领域的佼佼者,本文记录一下我对PHP面向对象部分的学习笔记。
先来一个复杂的例子:Mixin(掺入)
Ruby和Python可以用非常漂亮的语法支持掺入,PHP能实现吗?让我们试试吧。
参考其他语言的掺入示例可以查看这篇文章:设计原则:请重新审视“多重继承”,找机会拥抱一下“掺入(Mixin)”。
PHP5.4提供的有Traits机制可以方便的模拟掺入,下面的示例是采用5.3版本的机制模拟出来的。
期望的最终效果
1 class Playable
2 {
3 public function play($that)
4 {
5 echo "一起玩吧,".$that->name;
6 }
7 }
8
9 class Base extends _Object
10 {
11 public $name = "段光伟<br/>";
12 }
13
14 class Child extends Base {}
15
16 Base::implement(new Playable());
17
18 $base = new Base();
19 $child = new Child();
20
21 $base->play();
22 $child->play();
是不是特别像C#的扩展方法。
实现代码
1 class _Object
2 {
3 private static $mixins = array();
4
5 public static function implement($target)
6 {
7 $class = get_called_class();
8
9 if (!isset(self::$mixins[$class]))
10 {
11 self::$mixins[$class] = array();
12 }
13
14 foreach (get_class_methods($target) as $method)
15 {
16 self::$mixins[$class][$method] = $target;
17 }
18 }
19
20 public function class_name()
21 {
22 return self::get_class($this);
23 }
24
25 public function __call($method, $params)
26 {
27 $params = array_merge(array($this), $params);
28 $class = $class = get_called_class();
29
30 $mixin = $this->find_mixin($class, $method);
31
32 call_user_func_array($mixin, $params);
33 }
34
35 private function find_mixin($class, $method)
36 {
37 while ($class != NULL)
38 {
39 if (isset(self::$mixins[$class][$method]))
40 {
41 $target = self::$mixins[$class][$method];
42
43 return array($target, $method);
44 }
45
46 $class = get_parent_class($class);
47 }
48
49 throw new MethodException("方法 $method 不存在");
50 }
51 }
看不明白不要紧,继续看下文,回头再看这个。
面向对象
很多信息在注释中可以看到,在文中不会再重复一遍。
基本的类型声明
代码
1 <?php
2
3 header("content-type: text/html; charset=utf-8");
4
5 // 类型不能有修饰符。
6 // 成员以应用访问修饰符号,一共有三种访问修饰符:public、protected和private。
7 class TestClass {
8 // 属性默认访问级别是private。
9 private $private_property = "私共成员<br/>";
10
11 // var形式的默认访问级别是public。
12 var $public_property = "公共成员<br/>";
13
14 // 方法默认访问级别是public。
15 public function public_method() {
16 echo $this->private_property;
17 }
18 }
19
20 $test = new TestClass();
21
22 echo $test->public_property;
23 $test->public_method();
24
25 ?>
运行结果
1 // 公共成员
2 // 私共成员
继承:实现继承和接口继承
代码
1 <?php
2
3 header("content-type: text/html; charset=utf-8");
4
5 /*
6 * 使用interface关键字可以声明接口,接口以及接口的成员不能有任何修饰符。
7 */
8 interface Playable {
9 function play();
10 }
11
12 /*
13 * 使用abstract关键字可以声明抽象类和方法。
14 */
15 abstract class Base {
16 private $header = "";
17 private $rooter = "";
18
19 public function __construct($header, $rooter) {
20 $this->header = $header;
21 $this->rooter = $rooter;
22 }
23
24 public function write() {
25 $this->writeHeader();
26 $this->writeContent();
27 $this->writeRooter();
28 }
29
30 private function writeHeader() {
31 echo $this->header."<br/>";
32 }
33
34 private function writeRooter() {
35 echo $this->rooter."<br/>";
36 }
37
38 protected abstract function writeContent();
39 }
40
41 /*
42 * 使用final关键字可以禁止类型或方法被重写。
43 * 使用parent::在重写的方法里调用父类型的方法。
44 */
45 final class Child extends Base implements Playable {
46 private $content = "";
47
48 public function __construct($header, $rooter, $content) {
49 parent::__construct($header, $rooter);
50
51 $this->content = $content;
52 }
53
54 protected function writeContent() {
55 echo $this->content."<br/>";
56 }
57
58 public function play() {
59 echo "游戏中。。。<br/>";
60 }
61
62 public function __destruct() {
63 echo "析构中<br/>";
64 }
65 }
66
67 $child = new Child("头", "尾", "内容");
68 $child->write("段光伟");
69 $child->play();
70
71 ?>
运行结果
1 头
2 内容
3 尾
4 游戏中。。。
5 析构中
静态成员
代码
1 <?php
2
3 header("content-type: text/html; charset=utf-8");
4
5 class StaticBaseClass {
6 public static $StaticProperty = "父类静态属性<br/>";
7 const MAX = "父类常量<br/>";
8
9 public static function staticMethod() {
10 /* 在内部可以使用类名或self关键字,但是self访问的其定义时的类型,而不是运行时的类型,
11 * 这在子类和父类里有同名的静态成员和常量时会出现问题,为了避免这个问题可以使用static
12 * 关键字。
13 */
14
15 echo get_called_class()." self::\$StaticProperty ".self::$StaticProperty;
16 echo get_called_class()." StaticBaseClass::\$StaticProperty ".StaticBaseClass::$StaticProperty;
17 echo get_called_class()." static::\$StaticProperty ".static::$StaticProperty;
18
19 echo get_called_class()." self::MAX ".self::MAX;
20 echo get_called_class()." StaticBaseClass::MAX ".StaticBaseClass::MAX;
21 echo get_called_class()." static::MAX ".static::MAX;
22 }
23 }
24
25 class StaticChildClass extends StaticBaseClass {
26 public static $StaticProperty = "子类静态属性<br/>";
27 const MAX = "子类常量<br/>";
28 }
29
30 // 在外部必须使用类名访问。
31 StaticBaseClass::StaticMethod();
32 echo StaticBaseClass::$StaticProperty;
33 echo StaticBaseClass::MAX;
34
35 // 在子类中可以调用父类的静态成员和常量。
36 StaticChildClass::StaticMethod();
37 echo StaticChildClass::$StaticProperty;
38 echo StaticChildClass::MAX;
39
40 ?>
运行结果
1 StaticBaseClass self::$StaticProperty 父类静态属性
2 StaticBaseClass StaticBaseClass::$StaticProperty 父类静态属性
3 StaticBaseClass static::$StaticProperty 父类静态属性
4 StaticBaseClass self::MAX 父类常量
5 StaticBaseClass StaticBaseClass::MAX 父类常量
6 StaticBaseClass static::MAX 父类常量
7 父类静态属性
8 父类常量
9 StaticChildClass self::$StaticProperty 父类静态属性
10 StaticChildClass StaticBaseClass::$StaticProperty 父类静态属性
11 StaticChildClass static::$StaticProperty 子类静态属性
12 StaticChildClass self::MAX 父类常量
13 StaticChildClass StaticBaseClass::MAX 父类常量
14 StaticChildClass static::MAX 子类常量
15 子类静态属性
16 子类常量
又是魔法方法
代码
1 <?php
2
3 header("content-type: text/html; charset=utf-8");
4
5 /*
6 * 什么叫魔法方法:被解释器在某些特殊情况下调用的实例方法。
7 */
8 class WebDeveloper {
9 public $info = array();
10
11 // 当执行赋值时,而目标成员不存在会调用此方法。
12 public function __set($item, $value) {
13 $this->info[$item] = $value;
14 }
15
16 // 当执行取值时,而目标成员不存在会调用此方法。
17 public function __get($item) {
18 return $this->info[$item];
19 }
20
21 // 当执行isset方法时,而目标成员不存在会调用此方法。
22 public function __isset($item) {
23 return isset($this->info[$item]);
24 }
25
26 // 当执行unset方法时,而目标成员不存在会调用此方法。
27 public function __unset($item) {
28 unset($this->info[$item]);
29 }
30
31 // 当执行方法调用时,而目标方法不存在会调用此方法。
32 public function __call($method_name, $args) {
33 echo $method_name, var_dump($args), "<br/>";
34 }
35 }
36
37 $developer = new WebDeveloper();
38 $developer->name = "段光伟";
39
40 echo "{$developer->name}<br/>";
41 echo (isset($developer->name) ? "TRUE" : "FALSE")."<br/>";
42 unset($developer->name);
43 echo (isset($developer->name) ? "TRUE" : "FALSE")."<br/>";
44
45 $developer->saySomething('hi!','how are you!');
46
47 ?>
输出结果
1 段光伟
2 TRUE
3 FALSE
4 saySomethingarray(2) { [0]=> string(3) "hi!" [1]=> string(12) "how are you!" }
可调用对象(其实还是魔法方法)
代码
1 <?php
2 header("content-type: text/html; charset=utf-8");
3
4 class CallableClass
5 {
6 public function __invoke($x)
7 {
8 var_dump($x);
9 }
10 }
11
12 $obj = new CallableClass;
13
14 $obj(5);
15 call_user_func_array($obj, array(5));
16 var_dump(is_callable($obj));
17
18 ?>
输入结果
1 int(5) int(5) bool(true)
Reflection(反射)
代码
1 <?php
2
3 header("content-type: text/html; charset=utf-8");
4
5 /*
6 * 使用interface关键字可以声明接口,接口以及接口的成员不能有任何修饰符。
7 */
8 interface Playable {
9 function play();
10 }
11
12 /*
13 * 使用abstract关键字可以声明抽象类和方法。
14 */
15 abstract class Base {
16 private $header = "";
17 private $rooter = "";
18
19 public static $StaticProperty = "父类静态属性<br/>";
20 const MAX = "父类常量<br/>";
21
22 public function __construct($header, $rooter) {
23 $this->header = $header;
24 $this->rooter = $rooter;
25 }
26
27 public function write() {
28 $this->writeHeader();
29 $this->writeContent();
30 $this->writeRooter();
31 }
32
33 private function writeHeader() {
34 echo $this->header."<br/>";
35 }
36
37 private function writeRooter() {
38 echo $this->rooter."<br/>";
39 }
40
41 protected abstract function writeContent();
42 }
43
44 /*
45 * 使用final关键字可以禁止类型或方法被重写。
46 * 使用parent::在重写的方法里调用父类型的方法。
47 */
48 final class Child extends Base implements Playable {
49 public $content = "";
50 public static $StaticProperty = "子类静态属性<br/>";
51 const MAX = "子类常量<br/>";
52
53 public function __construct($header, $rooter, $content) {
54 parent::__construct($header, $rooter);
55
56 $this->content = $content;
57 }
58
59 protected function writeContent() {
60 echo $this->content."<br/>";
61 }
62
63 public function play() {
64 echo "游戏中。。。<br/>";
65 }
66
67 public function __destruct() {
68 echo "析构中";
69 }
70 }
71
72 $child = new Child("开始", "结束", "内容");
73
74 echo get_class($child).'<br/>';
75 print_r(get_class_methods(get_class($child)));
76 echo '<br/>';
77 print_r(get_class_vars(get_class($child)));
78 echo '<br/>';
79 echo $child->{"play"}();
80 ?>
输出结果
1 Child
2 Array ( [0] => __construct [1] => play [2] => __destruct [3] => write )
3 Array ( [content] => [StaticProperty] => 子类静态属性
4 )
5 游戏中。。。
6 析构中
备注
PHP属于:静态类型、鸭子类型、弱类型、解释执行的语言 ,后面详细介绍这些概念及其对应的语言特色。
|
|
|