好久没有写关于PHP的文章了,相关基础都比较简单,现在的框架都是面向对象的,对于掌握class类知识的要求很高。所以本文就来总结关于PHP中类的使用与命名空间的进阶知识。
在PHP中,类一个复合型的数据类型,里面包括了属于自己的 常量,变量(称为“属性”)以及函数(称为“方法”)。
在PHP中,将我们要使用的功能通过class类封装成一个功能模块,如:MySql数据库操作类、文件上传类、图片切割类、 文章列表分页类等,将要使用的功能以打包的形势归结在一起,这是类的重要特性之一。
<?php
//创建一个网站信息的类
class webInfo
{
//成员属性
public string $name;
public string $URL;
public string $description;
public int $age;
//成员方法
public function show()
{
echo '网站名称:' . $this->name . '<hr />';
echo '网站地址:' . $this->URL . '<hr />';
echo '网站介绍:' . $this->description . '<hr />';
echo '网站年龄:' . $this->age;
}
}
//实例化类
$mySite = new webInfo();
//设置属性
$mySite->name = '网络人';
$mySite->URL = 'http://www.55mx.com';
$mySite->description = 'http://www.55mx.com';
$mySite->age = 15;
//调用类的方法
$mySite->show();
我们可以将网站的信息封装起来,按照固定的格式对网站的数据进行处理。PHP有三种封装概念:Private私有(子类都不可访问),Protected保护(子类可访问),Public公开。
有时候网站比较有特色,我们需要增加一些数据或者功能,又不想破坏原来的数据格式,这里就需要使用到继承。
//定义一个55mx的类并继承webInfo的公开属性与方法
//通常情况下我们应该继承"抽象类",而不是直接的类,这里只为了演示。
//webInfo 是我们的父类,被55mx继承,别名:基类或超类。
//55mx称为子类,也可称为派生类。
class 55mx extends webInfo{
public string $type;
}
$55mx = new 55mx();
$55mx->type = "技术博客";
echo $55mx->type ;
继承可以有效的减少重复的代码,并扩展我们想要的功能。继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
因为PHP中弱类型语言,多态在PHP里表现得不强烈。 多态是指在面向对象中能够根据使用类的上下文来重新定义或改变类的性质和行为。
<?php
//定义接口
interface DoYourWork {
function ICanDo();
}
//定义“猫”的行为
class Cat implements DoYourWork {
public function ICanDo() {
echo "猫吃鱼~n";
}
}
//定义“狗”的行为
class Dog implements DoYourWork {
public function ICanDo() {
echo "狗吃肉~n";
}
}
//定义“奥特曼”的行为
class Altman implements DoYourWork {
public function ICanDo() {
echo "奥特曼打小怪兽~n";
}
}
//实例化
$cat = new Cat();//猫的实例
$cat->ICanDo();//猫的行为
$dog = new Dog();//狗的实例
$dog->ICanDo();//狗的行为
$altman = new Altman();
$altman->ICanDo();
可以看到,我们可以根据“类”的不同,返回自己的特点。这就是多态。多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
类和类之间应该是低耦合的(模块独立性强)。
继承通常是继承自抽象类,而不是具体类(使用abstract class定义的类)。
通常直接继承抽象类的具体类只有一层,在抽象类中用protected来限定子类可访问。
在上面的代码示例中已充分的对类属性与类方法进行了展示。我们通过下面的代码理解其概念:
<?php
//定义“类”,即:一件事物的抽象特点,并定义包含了数据的形式以及对数据的操作。
class MyClass
{
//成员变量,定义在类内部的变量。类的变量成员叫做属性,或者叫字段
public $var = '网络人'; //该变量的值对外是不可见的,但是可以通过成员函数(方法)访问,在类被实例化为对象后,该变量即可成为对象的属性。
//类常量的默认可见性是 public 。
const CONSTANT = '我的值一但设置,就不可以修改了';//类的常量,与变量不同的是,常量是固定值,不可修改。
//注意:类常量可以通过子类重新定义。PHP 8.1.0 起,除非设置为final
//成员函数或方法,定义在类的内部,可用于访问上面的对象的数据。
public function func()
{
echo '我是一个成员方法,我们可访问成员变量:' . $this->var;
}
}
$myClass = new MyClass(); //对象 − 是类的实例。
$myClass->func();//调用对象里的方法
在一个类中定义一个__construct方法作为构造函数(初始类/实例化时立即执行)。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
在一个类中定义一个__destruct(): void方法作为构造函数,它会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行(内存回收)。
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。
<?php
class MyDestructableClass
{
//构造函数可传参,无返回值,一般做初始化的工作
function __construct() {
print "我是构造函数输入的内容n";
}
//析构函数不能传参,无返回值,一般做回收工作
function __destruct() {
print __CLASS__ . "被销毁了~";
}
}
$obj = new MyDestructableClass();
spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。
<?php
spl_autoload_register(function ($class_name) {
require_once $class_name . '.php';//加载$class_name.php文件
});
$obj = new MyClass1();//尝试加载MyClass1.php
$obj2 = new MyClass2();//尝试加载MyClass2.php
spl_autoload_register将函数注册到SPL __autoload函数队列中。如果该队列中的函数尚未激活,则激活它们。
注意:PHP 8.0.0 之前,可以使用 __autoload() 自动加载类和接口,但 PHP 7.2.0 起弃用,在 PHP 8.0.0 起移除。
<?php
class MyWeb
{
public static $name = '55mx.com'; //静态属性
//静态方法
public static function getVule()
{
return self::$name;
}
//非静态方法,需要先new才能使用
public function getStaticValue()
{
return self::$name . PHP_EOL;
}
}
echo '静态访问:' . MyWeb::$name . PHP_EOL; //直接使用静态属性
echo '静态调用:' . MyWeb::getVule(); //直接使用静态方法
echo '错误调用:' . MyWeb::getStaticValue(); //错误使用了非静态方法
$neter = new MyWeb(); //实例化
echo '实例化后输出:' . $neter->getStaticValue();//实例化后使用
当一个类中,有一个抽象方法的时候,这个类就必须使用abstract关键字定义为抽象类。 且不能被实例化(只能被继承使用)。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。继承一个抽象类的时候,子类必须实现父类中的所有抽象方法。
<?php
//因为包括了抽象方法,所以必须定义成抽象类
abstract class WebInfo
{
// 强制要求子类定义这些方法
abstract protected function getSiteName(); //抽象方法
abstract protected function getURL($url); //抽象方法
// 普通方法(非抽象方法)
public function printOut()
{
echo $this->getSiteName() . "n" . $this->getURL('www.55mx.com');
}
}
//抽象类里有未实现的抽象方法,所以我们不能直接使用的
//$myWeb = new WebInfo();//报错: Cannot instantiate abstract class
//使用抽象类做为父类
class myWeb extends WebInfo
{
//实现抽象方法 getSiteName()
protected function getSiteName()
{
return "网络人";
}
//实现抽象方法 getURL()
protected function getURL($url)
{
return "网址:" . $url;
}
}
$myWeb = new myWeb(); //实例化
$myWeb->printOut();//调用抽象类里的方法
接口与抽象类有一点类似,其主要基于方法的规范,会抽象类里的抽象方法,只是其相对于抽象方法来说,更加独立。可让某个类通过组合多个方法来形成新的类。由于接口(interface)和类(class)、trait 共享了命名空间,所以它们不能重名。
接口就像定义一个标准的类一样,通过 interface 关键字替换掉 class 关键字来定义,但其中所有的方法都是空的。接口中定义的所有方法都必须是 public ,这是接口的特性。
<?php
//通过接口重写上面的抽象类
interface WebInfo
{
public function getSiteName(); //抽象方法
public function getURL($url); //抽象方法
public function printOut();//抽象方法
}
//实现接口
class myWeb implements WebInfo
{
//实现接口里的抽象方法 getSiteName()
public function getSiteName()
{
return "网络人";
}
//实现接口里的抽象方法 getURL()
public function getURL($url)
{
return "网址:" . $url;
}
//实现接口里的抽象方法 printOut()
public function printOut()
{
echo $this->getSiteName() . "n" . $this->getURL('www.55mx.com');
}
}
$myWeb = new myWeb(); //实例化
$myWeb->printOut();//调用方法
在其它语言里,接口的别名叫“协议”,所以接口定义的是我们商量好了,要去实现的功能。比如:车应该有转向功能、运动功能、计算速度功能、刹车功能等,我们在接口里将这些功能定义好,使用class定义一个皮卡车、小汽车、公交车类并使用接口,那么我们就需要在类里去实现接口里定义好的抽象方法。
上面的抽象类和接口的例子,看上去是不是类似?事实上,对于PHP编程来说,抽象类可以实现的功能,接口也可以实现。
抽象类和接口的区别重点不在于编程实现,而在于程序设计模式的不同。
一般来讲,抽象用于不同的事物,而接口用于事物的行为。
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/193
《【PHP进阶】一文搞懂面向对象编程之类(Class)的使用与知识》的网友评论(0)