[Day15]PHP Class 类别02

PHP Class 类别

1. class属性

类的变量成员叫做“属性”,或者叫“字段”、“特徵”,在PHP文档统一称为“属性”。属性声明是由关键字 public(公开),protected(非公开) 或者 private(私有) 开头,然後跟一个普通的变量声明来组成。属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指 PHP 脚本在编译阶段时就可以得到其值,而不依赖於运行时的信息才能求值。

在类的成员方法里面,可以用 ->(对象运算符):$this->property(其中 property 是该属性名)这种方式来访问非静态属性。

静态属性则是用 ::(双冒号):self::$property 来访问。

以下为属性声明范例

<?php
class SimpleClass
{
   // 错误的属性声明
   public $var1 = 'hello ' . 'world';
   public $var2 = <<<EOD
hello world
EOD;
   public $var3 = 1+2;
   public $var4 = self::myStaticMethod();
   public $var5 = $myVar;

   // 正确的属性声明
   public $var6 = myConstant;
   public $var7 = array(true, false);

   //在 PHP 5.3.0 及之後,下面的声明也正确
   public $var8 = <<<'EOD'
hello world
EOD;
}
?>

1. 类常量

可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。 常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。

如何定义和使用类常量,查看以下范例

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

$classname = "MyClass";
echo $classname::constant . "\n"; // 自 5.3.0 起

$class = new MyClass();
$class->showConstant();

echo $class::constant."\n"; // 自 PHP 5.3.0 起
?>

3. 类的自动加载

在编写有关於对象(OOP) 程序时,很多开发者为每个类新建一个 PHP 文件。这会带来一个烦恼:每个脚本的开头,都需要包含(include)一个长长的列表(每个类都有个文件)。

在 PHP 5 中,已经不再需要这样了。 spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最後一个机会加载所需的类。

尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_register() 函数。 spl_autoload_register() 提供了一种更加灵活的方式来实现类的自动加载(同一个应用中,可以支持任意数量的加载器,比如第三方库中的)。因此,不再建议使用 __autoload() 函数,在以後的版本中它可能被弃用

1. 自动加载范例

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类。

<?php
spl_autoload_register(function ($class_name) {
    require_once $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>
2. 自动加载在 PHP 5.3.0+ 中的异常处理
<?php
spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new Exception("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

// Want to load NonLoadableClass.
// Unable to load NonLoadableClass.

4. 构造函数和析构函数

构造函数

__construct(mixed ...$values = ""): void

PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作

注意: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。

1. 继承中的构造函数
<?php
class BaseClass {
    function __construct() {
        print "In BaseClass constructor\n";
    }
}

class SubClass extends BaseClass {
    function __construct() {
        parent::__construct();
        print "In SubClass constructor\n";
    }
}

class OtherSubClass extends BaseClass {
    // 继承 BaseClass 的构造函数
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>
2. 构造器函数

因此可以定义任何数量的参数,可以是必选、可以有类型、可以有默认值。构造器的参数放在类名後的括号里调用。

<?php
class Point {
    protected int $x;
    protected int $y;

    public function __construct(int $x, int $y = 0) {
        $this->x = $x;
        $this->y = $y;
    }
}

// 两个参数都传入
$p1 = new Point(4, 5);
// 仅传入必填的参数。 $y 会默认为0。
$p2 = new Point(4);
// 使用命名参数(PHP 8.0 起):
$p3 = new Point(y: 5, x: 4);
?>

如果一个类没有构造函数,以及构造函数的参数不是必填项时,括号就可以省略。

析构函数

__destruct(): void

1. 析构函数范例
<?php

class MyDestructableClass 
{
    function __construct() {
        print "In constructor\n";
    }

    function __destruct() {
        print "Destroying " . __CLASS__ . "\n";
    }
}

$obj = new MyDestructableClass();

和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。

此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。 析构函数即使在使用 exit() 终止脚本运行时也会被调用。

在析构函数中调用 exit() 将会中止其余关闭操作的运行。

注意: 析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同

注意: 试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误。

资料来源: https://www.php.net/


<<:  IOS、Python自学心得30天 Day-13 模组训练改善-5

>>:  [Day 11] 来自未来的资料 - 数据泄露(Data leakage)

[第二十二只羊] 迷雾森林舞会XVI 策略模式 Strategy Pattern

天亮了 昨晚是平安夜 关於迷雾森林故事 甜水镇 洛神:10号玩家请继续发言 10号: 我跟5号的想法...

day12 : argo gitops服务以及ingress (中)

昨天透过kustomize的方式做了base的yaml和规划了怎麽应用,那麽今天就来利用这些yaml...

Day_27:让 Vite 来开启你的Vue之 跌入深坑偶像剧_ v-if & v-for 他俩不能在一起啊

Hi Dai Gei Ho~ 我是 Winnie ~ 今天的文章中,我们要来说说 v-if & v-...

[13th][Day4] 容器四五事

检查container 进程/处理程序(process) ps -aux 恩 .... 是个非常乾净...

Day 10 阿里云架设网站-资料库搬迁上云

接着上一篇文章我们建立好代管式资料库後,里面目前还没有资料,将如何把资料搬迁到云端资料库中呢? 目...