2.4PHP类型之类(Class)

1.类声明

class 类名
{
    //类体
}

2.继承

一个类可以在类声明中使用 extends 关键字继承另一个类的属性、常量和方法。

一个类不支持继承多个父类,只能继承一个父类。

class 子类 extends 父类
{
    //类体
}

3.构造函数和析构函数

3.1构造函数声明

function __construct(参数) 
{
    //构造函数体
}

具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。

如果子类没有定义构造函数,则会从父类继承(前提是父类构造函数没有被定义为 private 的话)。

如果子类中定义了构造函数,则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()

一个类可以没有构造函数,构造函数可以没有参数,构造函数体可以是空的。

3.2构造函数提升(Promotion)

构造函数就像普通函数一样,也支持访问控制修饰符(visibility modifier)。

当构造函数参数带访问控制修饰符时,PHP 会同时把它当作构造函数参数和类属性, 并将参数值赋值给类属性。 构造函数体可以是空的,或者包含其它语句。 参数值赋值到对应类属性后执行构造函数体中额外的代码语句。

//构造函数体内将构造函数的参数赋值给类属性
class Point 
{
    protected int $x;
    protected int $y;

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

//构造函数属性提升简写方式
class Point 
{
    public function __construct(protected int $x, protected int $y = 0) 
    {
    }
}

3.3析构函数

function __destruct() 
{
    //析构函数体
}

当某个对象没有被任何引用或者显式调用析构函数时,析构函数才会被调用。

如果子类没有定义析构函数,则会从父类继承(前提是父类析构函数没有被定义为 private 的话)。

如果子类中定义了析构函数,则不会隐式调用其父类的析构函数。要执行父类的析构函数,需要在子类的析构函数中调用 parent::__destruct()

4.创建对象

//构造函数有参数需要传递
$变量 = new 类名(参数1, 参数N);

//没有构造函数 或 构造函数的参数非必选参数,则类名后的括号可省略。
$变量 = new 类名();

5.访问成员

可以用 ::(范围解析运算符,或称双冒号)来访问静态成员,类常量,还可以用于覆盖类中的属性和方法。

//访问类属性和方法
类名::$类属性;
类名::类方法();
类名::类常量;

可以用 ->(对象运算符)来访问实例属性和方法。

//访问实例属性和方法
$对象名->实例属性;
$对象名->实例方法();

6.抽象类和抽象方法

abstract class 类名 
{
    abstract function 方法名称(): 返回类型;
    abstract function 方法名称(参数): 返回类型;
    function 方法名称(参数): 返回类型 
    {
        //具体实现
    } 
}

如果一个类里面声明了至少一个抽象方法,那么这个类就必须声明为抽象类。抽象类可以声明有具体实现的方法。

抽象方法体内不能声明具体实现。

当子类从抽象类继承时,子类必须实现定义在父类中的所有抽象方法。

抽象类不能被实例化。

7.匿名(Anonymous)类

匿名类支持 传递参数给匿名类的构造函数、继承其它类、实现接口、导入trait。

//显示声明类
class Logger
{
    public function log($msg)
    {
        echo $msg;
    }
}

$util->setLogger(new Logger());

//匿名类
$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});

8.覆盖(Override)

子类会继承父类的属性、常量和方法,父类中被继承的属性、常量和方法可以通过在子类中使用同样的名字重新声明来覆盖。但是如果父类中定义的常量或方法时使用了 final 关键字,则该常量或方法不可以被覆盖。可以通过 parent:: 来访问父类中被覆盖的方法或静态属性。

8.1方法覆盖

当子类覆盖父类的方法时,子类方法的签名必须兼容父类方法。这就是著名的里氏替换原则(Liskov Substitution Principle,简称 LSP)。具体签名兼容规则是指:

  • 父类方法与子类方法之间遵守协变与逆变规则。
  • 父类方法的必选参数,在子类可以改为默认值参数。
  • 子类的新增参数可以为默认值参数。

不过 构造函数 和 私有(private)方法不需要遵循签名兼容规则。

9.重载(Overloading)

PHP中的重载与其它绝大多数面向对象语言不同。传统的重载是在类中提供多个同名的方法,但各方法的参数类型和个数不同来实现重新加载具体哪个方法的。而PHP的重载为:当调用当前作用域下未声明或不可见的属性或方法时,对应行为的重载方法(通过魔术方法实现的)会被调用。

所有的重载方法都必须被声明为 public,不可以被声明为 static

9.1属性重载

属性重载方法值可以在对象上下文(->)工作,在静态上下文(::)这些魔术方法不会被触发。

属性重载方法描述
__set()当赋值给 未声明或不可见(protected 或 private)的属性时,__set() 会被调用。
__get()当读取 未声明或不可见(protected 或 private)的属性的值时,__get() 会被调用。
__isset()当在 未声明或不可见(protected 或 private)的属性上调用 isset() 或 empty() 函数时,__isset() 会被调用。
__unset()当在 未声明或不可见(protected 或 private)的属性上调用 unset() 函数时,__unset() 会被调用。

9.2方法重载

方法重载方法描述
__call()在对象上下文,当调用一个不可见的方法时,__call() 会被调用。
__callStatic()在静态上下文,当调用一个不可见的方法时,__callStatic() 会被调用。

10.::class

使用 ::class 可以获取类的完全限定名称。

//用在类上面
<?php
namespace NS 
{
    class ClassName 
    {
    }

    echo ClassName::class;
}
?>

//输出
NS\ClassName
//用在对象上面
<?php
namespace NS 
{
    class ClassName 
    {
    }
}
$c = new ClassName();
print $c::class;
?>

//输出
NS\ClassName

11.final类

final 关键字加在类前面可以防止父类被子类继承。

final class A
{
    //类体
}

12.readonly类

声明为 readonly 的类意味着类里面的所有属性均为 readonly 属性,除了未声明类型的属性和静态属性。

readonly class 类名
{
    //类体
}

13.self、parent、static、$this类型

类型描述
self指向当前类
parent指向当前类的父类
static作为返回类型,指向当前类
$this指向当前实例

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/php/phplang/3457.html

(0)
上一篇 2021年2月3日 19:47
下一篇 2021年2月4日 22:18

相关推荐

  • 2.8PHP类型之枚举(Enum)

    枚举(enum)本质是一个类(Class), 它的各种条目(case)是这个类的单例对象,既然条目是对象,那就意味着条目可以被用在对象可以被使用在的地方。 1.纯粹(Pure)枚举 如果条目仅仅为当前枚举的单例对象,条目没有关联数据,就称为“纯粹条目”(Pure Case)。仅包含纯粹条目的枚举,就称为“纯粹枚举“(P…

    PHP语言教程 2021年2月8日
    06680
  • 2.11PHP类型之生成器(Generator)

    1.生成器类与自定义类 生成器(Generator)类是PHP语言内置的类,与自定义类一样都实现了 Iterator 接口,提供对象迭代的实现方式。 1.1优势:性能更好 一个简单的例子就是使用生成器函数来重新实现 range() 函数。标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值,然后…

    PHP语言教程 2021年2月11日
    0300
  • 1.2PHP语言的注释(Comment)

    1.单行注释 2.多行注释 3.文档注释

    PHP语言教程 2021年1月2日
    06210

发表回复

登录后才能评论