Date
Dec. 22nd, 2024
 
2024年 11月 22日

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
The Founder and CEO of Infeca Technology.
Developer, Designer, Blogger.
Big fan of Apple, Love of colour.
Feel free to contact me.
反曲点科技创始人和首席执行官。
开发、设计与写作皆为所长。
热爱苹果、钟情色彩。
随时恭候 垂询