返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >猿创征文|学习记录之 PHP 中的面向对象编程
  • 190
分享到

猿创征文|学习记录之 PHP 中的面向对象编程

php学习开发语言面向对象OOP 2023-08-31 17:08:03 190人浏览 薄情痞子
摘要

本文目录 一、什么是面向对象编程二、类和对象(一)定义类(二)实例化类(创建对象)(三)类中的变量(四)类中的方法1. 定义方法2. 调用方法3. 方法的参数4. 方法参数的默认值5. 方法的

本文目录

一、什么是面向对象编程

面向对象,准确地说应该叫做 “面向对象编程”。

面向对象编程( Object Oriented Programming,OOP )是一种计算机编程架构,它能使代码更加简洁,更易于维护,并且具有更强的可重用性。

二、类和对象

类( class )和对象( object )是面向对象编程的核心概念。

类是对一类事物的描述,它定义了事物的抽象特点,类的定义包含了数据的形式以及对数据的操作。

对象是类的实例,是实际存在的该类事物的某个个体。

在计算机中,可以理解为类是一个抽象模型,而对象是实实在在存储在内存区域中的一个实体。

(一)定义类

PHP 也是通过关键字 class 加类名来声明类的,与一个类关联的代码必须用大括号括起来。

其定义的格式如下:

phpclass Test{}

类名可以是任意数字和字母的组合,但不能以数字开头,一般采用首字母大写,而后每个单词首字母大写的形式,以便于阅读。

(二)实例化类(创建对象)

class Test{}// 实例化类$test = new Test();

(三)类中的变量

类中的变量,是指在 class 中声明的变量,也称成员变量(也称为属性),用于存放数据信息。

成员变量与普通变量相似,其定义的格式如下:

key $age = "23";

关键字 key 可以是 publicprotectedprivatestaticfinal 中的任意一个。

public(公有):表示变量在类的内部和外部都可以被读取和修改。
protected(受保护):表示变量可以被其自身以及其子类和父类读取和修改。
private(私有):表示变量只能被其定义所在的类访问。

要访问成员变量,可以使用 “->” 符号连接对象和变量名。

class Test{// 声明成员变量    public $age = "23";}// 实例化类$test = new Test();// 读取成员变量 $age 的值echo $test->age; // 23

也可以给成员变量赋值(public 修饰的):

class Test{    public $age = "23";}// 实例化类$test = new Test();$test->age = 25;echo $test->age; // 25

(四)类中的方法

类中的方法(又叫成员方法)是指在类中声明的特殊函数。

它与普通函数的区别在于,普通函数实现的是某个独立的功能;而成员方法是实现类的一个行为,是类的一部分。

1. 定义方法
class Test{    public $age = "23";        // 定义 say 方法    public function say()    {        echo '这是say方法';    }}
2. 调用方法
class Test{    public $age = "23";    public function say()    {        echo '这是say方法';    }}// 实例化类$test = new Test();// 调用 say 方法$test->say(); // 这是say方法
3. 方法的参数
class Test{    public function say($name)    {        echo 'name的值为' . $name;    }}$test = new Test();$test->say('tom'); // name的值为tom

如果声明类的方法时带有参数,而调用该方法时没有传递参数,或者参数数量不够,系统将会报错。如果参数数量超过方法本身定义参数的数量,PHP会忽略后面多出来的参数,不会报错。

4. 方法参数的默认值
class Test{    public function say($name = '默认值')    {        echo 'name的值为' . $name;    }}$test = new Test();// 调用时不传参$test->say(); // name的值为默认值
5. 方法的返回值
class Test{    public function say($name = '默认值')    {    // 使用 return 关键字返回值        return 'name的值为' . $name;    }}$test = new Test();// 使用 echo 将返回值输出echo $test->say('jack'); // name的值为jack

三、$this 操作符的使用

如果想在类内调用本类中的成员变量或成员方法,就要使用伪变量 $this->$this 就是指本身,所以 $this-> 只能在类的内部使用。

class Test{    public $name = '小明';    public $age = 23;    public function say()    {        // 使用 $this 访问本类中的 $name 变量        echo '我的名字是:' . $this->name;        echo '
'
; // 使用 $this 访问本类中的 sayAge 方法 $this->sayAge(); } public function sayAge() { echo '我的年龄是:' . $this->age; }}$test = new Test();$test->say(); // 我的名字是:小明 我的年龄是:23

四、构造方法

构造方法是一种特殊的方法,主要用于在创建对象时初始化对象,即为对象成员变量赋初始值,总与 new 运算符一起使用在创建对象的语句中。

class Test{// 定义成员变量    public $name;    public $age;    public $sex;// 定义构造方法    public function __construct($name, $age, $sex)    {    // 为成员变量赋值        $this->name = $name;        $this->age = $age;        $this->sex = $sex;    }}// 实例化类并给构造方法传值$test = new Test('小明', '25', '男');echo $test->name;echo $test->age;echo $test->sex;// 输出:小明 25 男

构造方法会在实例化类时自动执行。

注意:方法开始的 “__” 是两条下划线 “_” 。

五、析构方法

析构方法(析构函数)与构造方法正好相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数以释放内存。

class Test{    public function __destruct()    {        echo '我是析构方法';    }}$test = new Test();

PHP 使用 “垃圾回收” 机制,自动清除不再使用的对象,释放内存。就是说即便不使用 unset 函数,系统也会自动调用析构方法,此处只是说明析构方法在何时会被调用。一般情况下不用手动创建析构方法。另外,当对象没有被引用时也同样会被销毁。

六、类的继承

类可以从其他类中扩展出来,扩展或派生出来的类拥有其基类(父类)的所有变量和函数,并包含所有派生类(子类)中定义的新功能,这称为继承。

继承是面向对象最重要的特点之一,可以实现对类的复用。

(一)如何继承类

PHP 是单继承的,一个扩充类只能继承一个基类,但一个父类却可以被多个子类所继承。

子类不能继承父类的私有属性和私有方法。

PHP 5 之后的版本中,类的方法可以被继承,类的构造函数也能被继承。

当子类被实例化时,PHP 会先在子类中查找构造方法,如果子类有自己的构造方法,PHP 会优先调用子类中的构造方法;当子类中没有时,PHP 会转而去调用父类中的构造方法。

继承使用关键字 extends 来声明:

// 定义父类 Testclass Test{    public $name = '小明';    protected $age = 22;    private $sex = '男';public function __construct()    {        echo '我是父类中的构造方法,当继承我的子类中没有构造方法时,我就执行。';    }public function sayName(){echo $this->name;}protected function sayAge(){echo $this->age;}private function saySex(){echo $this->sex;}}// 定义子类 Test2 继承父类 Testclass Test2 extends Test{    public function __construct()    {        echo '我是子类中的构造方法,我会优先执行';    }}// 实例化子类$test2 = new Test2();echo $test2->name; // 输出:小明echo $test2->age;// 报错:Cannot access protected property Test2::$age// protected 修饰的成员变量不能在类外使用echo $test2->sex; // 无内容,private 修饰的成员变量不会被继承$test2->sayName(); // 输出:小明$test2->sayAge();// 报错:Call to protected method Test::sayAge() from context// protected 修饰的成员方法不能在类外使用$test2->saySex(); // 无内容,private 修饰的成员方法不会被继承$test2->sayAge2(); // 输出:22// 在子类的内部,可以访问 protected 修饰的成员变量

总结权限修饰符的修饰范围:
权限修饰符的修饰范围

(二)方法的重写

如果从父类继承的方法不能满足子类的需求,可以对其进行改写,该过程叫做方法的覆盖(override),也称为方法的重写。

在对父类的方法进行重写时,子类中的方法必须与父类中对应的方法具有相同的名称。

class Test{    protected function say()    {        echo '我是父类中的 say 方法。';    }}// 定义子类 Test2 继承父类 Testclass Test2 extends Test{// 此处的权限可以是 protected 或 public ,但不能是 private 。// 可以加参数。    public function say($param = '')    {        echo '我是子类中的 say 方法。';        echo '父类中的 say 方法不满足我的要求,我被重写。';    }}$test2 = new Test2();$test2->say();// 我子父类中的 say 方法。父类中的 say 方法不满足我的要求,我被重写。

在重写方法时需注意以下几点:

  1. 子类中的覆盖方法不能使用比父类中被覆盖方法更严格的访问权限。在声明方法时如果没有定义访问权限,则权限默认为 public
  2. 子类中的覆盖方法可以拥有与父类中被覆盖方法不同的参数数量。
  3. 父类中的构造方法也可以被重写。

(三)调用父类中的方法

即使父类中的方法被重写,但父类中的方法仍保留其功能,可以使用 Parent 关键字调用父类中的方法。

class Test{    protected function say()    {        echo '我是父类中的 say 方法。';    }}// 定义子类 Test2 继承父类 Testclass Test2 extends Test{    public function say()    {        // 调用父类中的 say 方法        Parent::say();        echo '我子父类中的 say 方法。';    }}$test2 = new Test2();$test2->say();// 我是父类中的 say 方法。我子父类中的 say 方法。

七、静态变量(方法)

前面的内容中,类被当做模板,对象被当做活动组件,面向对象编程中的操作都是通过类的实例(对象)来完成的。

事实上,并不是所有的变量(方法)都要通过创建对象来调用。

声明类属性或方法为 static(静态),就可以不实例化类而直接访问。

使用静态成员,除了不需要实例化对象外还有一个好处,就是在对象被销毁后,依然保存被修改的静态数据,以便下次继续使用。

class Test{    public static $n = 1;    public static function test1()    {        // 在类内使用 self 关键字访问静态成员变量        echo self::$n;    }}// 类外访问静态成员变量 $necho Test::$n; // 1// 类外访问静态成员方法 test1Test::test1(); // 1// 仍然可以实例化后调用静态方法$t = new Test();$t->test1();  // 1

静态属性不能通过一个类已实例化的对象来访问,但静态方法可以。由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。静态属性不可以由对象通过 -> 操作符来访问。

class Test{    public static $n = 1;    public static function test1()    {        echo '值为:' . self::$n;        self::$n++;        echo '
'
; }}Test::test1(); // 值为:1Test::test1(); // 值为:2

可以发现两次返回的结果是有联系的。

八、final 类和方法

继承为类的应用带来了巨大的灵活性。

通过覆写类和方法,调用同样的成员方法可以得到完全不同的结果,但有时候,也需要类或方法保持不变,这就需要用到 final 关键字。

// 使用 final 修饰类final class Test {}class Test2 extends Test {}

报错:Class Test2 may not inherit from final class (Test)

class Test{    // 使用 final 修饰成员方法    final public function say()    {        echo 'function say';    }}class Test2 extends Test{    // 子类重写父类 say 方法    public function say()    {        echo 'function say';    }}

报错:Cannot override final method Test::say()

总结:

  1. final 关键字修饰的类不能被继承。
  2. final 关键字修饰的成员方法不能被重写。

当不希望一个类被继承时,可以将该类声明为 final 类型;当不希望类中的某个方法被子类重写时,可以设置其为 final 类型的方法。

九、常量属性

可以把在类中始终保持不变的值定义为常量。

PHP 中使用 const 关键字定义常量,在定义和使用常量时不需要使用 $ 符号。

另外使用 const 定义的常量名称一般都大写。

类中常量的使用方法类似于静态变量,所不同的是它的值不能被改变。

class Test{// 定义常量    const VERSION = '1.0';    public function getVersion()    {        // 类内访问常量        echo self::VERSION;    }}// 类外访问常量echo Test::VERSION; // 1.0$t = new Test();$t->getVersion(); // 1.0

常量的值必须是一个定值,不能是变量、类属性、数学运算的结果或函数调用。

十、abstract 类和方法

使用 abstract 关键字修饰的类或方法,称为抽象类或者抽象方法。

抽象类不能被直接实例化,只能作为其他类的父类来使用。

抽象方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

子类可以继承它并通过实现其中的抽象方法,来使抽象类具体化。

任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么该类就必须被声明为抽象的。

抽象类可以像普通类那样去声明,但必须以分号而不是方法体结束。

// 使用 abstract 声明抽象类abstract class Test{    // 抽象方法只有方法的声明部分,没有方法体。    public abstract function say($name);}// 抽象类不能被实例化。// $t = new Test();// 报错:Cannot instantiate abstract class Test 。// 抽象类只能作为其它类的父类来使用class Test2 extends Test{    // 继承一个抽象类的时候,父类中的所有抽象方法在子类中必须被重写。    // 这些方法的访问控制必须和父类中一样(或者更为宽松)。    public function say($name)    {        echo 'function say echo:' . $name;    }}$t = new Test2();$t->say('hello'); // function say echo:hello

抽象方法只有方法的声明部分,没有方法体。

继承一个抽象类的时候,父类中的所有抽象方法在子类中必须被重写,这些方法的访问控制必须和父类中一样(或者更为宽松)。

例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。

方法的调用方式必须匹配,即类型和所需参数数量必须一致。

十一、接口

PHP 只支持单继承,父类可以派生出多个子类,但一个子类只能继承自一个父类。

接口有效地解决了这一问题。

接口是一种类似于类的结构,使用它可以指定某个类必须实现哪些方法。

它只包含方法原型,不需要包含方法体。

这些方法原型必须被声明为 public,不可以为 privateprotected

// 声明接口 1interface Test1{    public function say1();}// 声明接口 2interface Test2{    public function say2();}// 实现接口class Test implements Test1, Test2{    public function say1()    {        echo '实现接口1中的say1方法';    }    public function say2()    {        echo '实现接口2中的say2方法';    }}$t = new Test();$t->say1(); // 实现接口1中的say1方法$t->say2(); // 实现接口2中的say2方法

实现接口的类中必须实现接口中定义的所有方法,除非该类被声明为抽象类。

十二、魔术方法

PHP 中以两个下划线 “__” 开头的方法被称为“魔术方法”,是系统预定义的方法。

如果需要使用这些魔术方法,必须先在类中定义。

构造方法 “__construct()” 和析构方法 “__destruct()” 都属于魔术方法。

魔术方法的作用、方法名、使用的参数列表和返回值都是规定好的,在使用这些方法时,需要用户自己根据需求编写方法体的内容。

使用时无须调用,它会在特定情况下自动被调用。

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除魔术方法外,建议不要以 __ 为前缀。

(一)__set() 方法

PHP 程序试图给一个未定义的属性赋值时,就会调用 __set() 方法。

__set() 方法包含两个参数,分别表示变量名称和变量值,两个参数均不可省略。

class Test{    // 定义 __set() 方法    public function __set($name, $value)    {        echo '正在试图给一个未定义的成员变量赋值,变量名称:' . $name . ',变量值:' . $value . '。';    }}$t = new Test();$t->name = 'test'; // 正在试图给一个未定义的成员变量赋值,变量名称:name,变量值:test。

(二)__get() 方法

当需要调用一个未定义或不可见(私有)的成员变量时,可以使用 __get() 方法读取变量值。

__get() 方法有一个参数,表示要调用的变量名。

class Test{private $age = 21;    // 定义 __get() 方法    public function __get($name)    {        echo '正在试图获取一个未定义的成员变量的值,变量名称:' . $name . '。';    }}$t = new Test();echo $t->name; // 正在试图获取一个未定义的成员变量的值,变量名称:name。echo $t->age;  // 获取私有成员变量也会触发 __get 方法。

(三)__call() 方法

程序试图调用不存在或不可见的成员方法时,PHP会自动调用 __call() 方法来存储方法名及其参数。

该方法包含 “方法名” 和 “方法参数” 两个参数,其中的 “方法参数” 以数组形式存在。

class Test{    // 定义 _call() 方法    public function __call($name, $params)    {        echo '正在试图调用一个未定义的成员方法,方法名称:' . $name . '。';        echo '
'
; echo '传递的参数有:'; print_r($params); }}$t = new Test();echo $t->say('a', 'b');// 正在试图调用一个未定义的成员方法,方法名称:say。// 传递的参数有:Array ( [0] => a [1] => b )

(四)__toString() 方法

__toString() 方法用于在使用 echoprint 输出对象时,将对象转化为字符串

class Test{    // 定义 __toString() 方法    public function __toString()    {        return 'string';        // 这里必须返回一个字符串    }}$t = new Test();echo $t;

来源地址:https://blog.csdn.net/ZhangJiWei_2019/article/details/126636392

--结束END--

本文标题: 猿创征文|学习记录之 PHP 中的面向对象编程

本文链接: https://lsjlt.com/news/386254.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作