Date
May. 20th, 2024
 
2024年 4月 13日

Post: PHP Primer 021 : 面向对象

PHP Primer 021 : 面向对象

Published 12:01 Jan 25, 2012.

Created by @ezra. Categorized in #Programming, and tagged as #PHP.

Source format: Markdown

Table of Content

有了前面的基础知识,就可以开始学习 PHP 中的面向对象了。

类的定义

简单来说定义一个类的方式是这样的:

<?php
class Person {
    public $name = 'Meniny';
    public function getName() {
        return $this->name; 
    }
}
?>

类的实例化

那么创建这个类的实例则是这样的:

<?php
$person = new Person();
?>

或者兜个圈子:

$clsName = 'Person';
$person = new $clsName();

访问控制

上面用到的访问控制关键字,和主流语言没什么不同:

  • public : 公开

  • protected : 受保护

  • private : 私有

注意: 属性变量必须声明访问控制,方法可以省略方法控制声明,默认为 public

<?php
class Guy {
    public $name = 'Tom';
    protected $age = 20;
    private $wealth = 100000;
}

$guy = new Guy();
echo $guy->name;        // ✔ 正确
echo $guy->age;     // ✗ 错误
echo $guy->wealth;  // ✗ 错误
?>

静态方法

此外,你还可以使用 static 关键字来修饰类中的方法使其成为静态方法,静态方法不需要实例对象,可以通过类名调用,操作符为双冒号(::)。

<?php
class Pet {
    public static function getOwner() {
        return 'Meniny'; 
    }
}
echo Pet::getOwner();
?>

或者再兜个圈子:

$func = 'getOwner';
$cls = 'Pet';
echo $cls::$func();

类的继承

PHP 中的类同样可以集成,通常实现一个类的集成是这样的:

<?php
class Creature {
    // ....
}

class Human extends Creature {
    // ....
}
?>

构造与析构

在类中我们可以使用 __construct() 定义构造函数,供该类实例化时调用。

注意,__construct() 前面是两个连续的下划线(_)

<?php
class Car {
    function __construct() {
        print "construct()";
    }
}

$car = new Car();
?>

在执行上面 $car = new Car(); 代码时,构造函数将会被调用,因此在控制台应当有字符串 construct() 输出。

如果定义了构造函数,那么父类中的构造函数将不会再被调用,除非进行显式调用。

<?php
class Creature {
    function __construct() {
        print "Some Creature\n";
    }
}

class Human extends Creature {
    function __construct() {
        parent::__construct();
        print "Human\n";
    }
}

$human = new Human();
?>

类似的,我们还可以使用 __destruct() 定义析构函数,供对象销毁时调用。

<?php
class Car {
    function __construct() {
        print "construct()";
    }
    function __destruct() {
        print "destruct()";
    }
}

$car = new Car(); // 输出"construct()"
unset($car); // 输出"destruct()"
?>

因为 PHP 代码之行结束后主动回收和销毁对象,因此通常来说,很少显式对对象进行销毁操作。

重载

PHP 中的重载指的是属性和方法的动态创建。

属性重载

属性重载通过 __set__get__isset__unset 来实现。

<?php
class Car {
    private $ary = array();

    public function __set($key, $val) {
        $this->ary[$key] = $val;
    }

    public function __get($key) {
        if (isset($this->ary[$key])) {
            return $this->ary[$key];
        }
        return null;
    }

    public function __isset($key) {
        if (isset($this->ary[$key])) {
            return true;
        }
        return false;
    }

    public function __unset($key) {
        unset($this->ary[$key]);
    }
}
$car = new Car();
// 动态创建
$car->name = 'BMW';
echo $car->name;
?>

方法重载

方法重载通过 __call 来实现。如果调用不存在的方法的将转为参数调用 __call 方法,如果调用不存在的静态方法用 __callStatic 重载。

<?php
class Car {
    public $price = 100000;
    public function __call($name, $args) {
        if ($name == 'raiseThePrice') {
            $this->price += 2000;
        }
    }
}
$car = new Car();
// 调用不存在的方法
$car->raiseThePrice();
echo $car->price;
?>

克隆对象

在某些情况下,我们可能需要将某个对象复制一份使用,这时我们可以使用 clone 关键字来进行克隆操作,通过调用 __clone() 方法设置属性。

<?php
class Sheep {
    public $name = 'Dolly';
    public function __clone() {
        $obj = new Sheep();
        $obj->name = $this->name;
    }
}
$s1 = new Sheep();
$s1->name = 'Dolly the Sheep';
$s2 = clone $s1;
var_dump($s2);
?>

对象序列化与反序列化

  • 要实现对象序列化,需要通过 serialize 方法进行操作。

  • 要实现对象反序列化,需要通过 unserialize 方法进行操作。

<?php
    class Secret {
        public $name = 'the Secret';
    }
    $a = new Secret();
    // 序列化
    $str = serialize($a); 
    echo $str."\n";
    // 反序列化
    $b = unserialize($str); 
    var_dump($b);
?>

对象比较

对于同一个类的两个实例,要判断是否所有属性都相等,可以使用 == 运算符。

对于两个变量是否引用字同一对象时,可以使用 === 运算符。

Pinned Message
HOTODOGO
I'm looking for a SOFTWARE PROJECT DIRECTOR / SOFTWARE R&D DIRECTOR position in a fresh and dynamic company. I would like to gain the right experience and extend my skills while working in great teams and big projects.
Feel free to contact me.
For more information, please view online résumé or download PDF
本人正在寻求任职 软件项目经理 / 软件技术经理 岗位的机会, 希望加⼊某个新鲜⽽充满活⼒的公司。
如有意向请随时 与我联系
更多信息请 查阅在线简历下载 PDF