PHP面向对象OOP编程

Posted willem_chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP面向对象OOP编程相关的知识,希望对你有一定的参考价值。

php面向对象OOP编程

  • class: 类声明
  • new: 类实例化
  • public: 公开成员,随处可见
  • protected: 受保护成员,仅在当前类或子类中可见
  • private: 私有成员, 仅在当前类可见
  • spl_autoload_register(): 自动加载器
  • extends: 类的扩展
  • abstract 抽象类
  • interface 接口
  • static: 声明类的静态成员
  • $this: 实例引用
  • self: 类的引用
  • trait: 类功能横向扩展

面向对象的概念

面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持。

如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的。

下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法。

我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境。和其他编程语言有所不同的是,在PHP中,操作数据库的 是一系列的具体功能函数(如果你不使用ODBC接口的话)。

这样做虽然效率很高,但是封装却不够。如果有一个统一的数据库接口,那么我们就可以不对程序做 任何修改而适用于多种数据库,从而使程序的移植性和跨平台能力都大大提高。

对象的基本组成

对象的组成元素:

是对象的数据模型,用于描述对象的数据,又称为对象的属性,或者对象的成员变量。

对象的行为::

是对象的行为模型,用于描述对象能够做什么事情,又被称为对象的成员方法。

对象特点

每一个对象都是独一无二的

对象是一个特定的事物,他的职能是完成特定功能

对象是可以重复使用

类的概念

物以类聚,把具有相似特性的对象对垒到一个类中,类定义了这些相似对象拥有的相同的属性和方法

类是相似对象的描述,成为类的定义,是该类对象的蓝图或者原型

类的对象称为一个类的实例(Instance)

类的属性和方法统称为类成员

类的实例化

类的实例化:通过类定义创建一个类的对象

类的定义属性值都是空或默认值,而对象的属性都有具体的值

类的定义

类的定义以关键字class开始,后面跟着这个类的名称。类的命名通常每个单词的第一个字母大写,以中括号开始和结束

类的实例化为对象时使用关键字new,new之后紧跟类的名称和一对圆括号

对象中得成员属性和方法可以通过->符号来访问

OOP面向对象编程

面向对象编程(Object Oriented Programming,OOP)是一种编程思想,在很多现代编程语言中都有面向对象编程的概念。

面向对象编程的思想就是把具有相似特性的事物抽象成类,通过对类的属性和方法的定义实现代码共用。将实现某一特定功能的代码部分进行封装,这样可被多处调用,而且封装的粒度越细小被重用的概率越大。

而面向对象编程的继承性和多态性也提高了代码的重用率。总之,面向对象编程充分地体现了软件编程中的“高内聚,低耦合”的思想。

PHP 之所以能够成为 Web 开发领域的主流语言,对面向对象开发模式的支持也是重要原因之一。

面向对象编程的特性

面向对象编程具有封装、继承、多态三大特性,它们迎合了编程中注重代码重用性、灵活性和可扩展性的需要,奠定了面向对象在编程中的地位。

1、继承
继承就是派生类(子类)自动继承一个或多个基类(父类)中的属性与方法,并可以重写或添加新的属性或方法。继承这个特性简化了对象和类的创建,增加了代码的重用性。

例如,已经定义了 A 类,接下来准备定义 B 类,而 B 类中有很多属性和方法与 A 类相同,那么就可以用 B 类继承 A 类,这样就不用再在 B 类中定义 A 类中已有的属性和方法,从而可以在很大程度上提高程序的开发效率。

继承分为单继承和多继承,PHP 目前只支持单继承,也就是说一个子类有且只有一个父类。

2、封装
封装就是将一个类的使用和实现分开,只保留有限的接口(方法)与外部联系。对于用到该类的开发人员,只要知道这个类该如何使用即可,而不用去关心这个类是如何实现的。这样做可以让开发人员更好地把精力集中起来专注于别的事情,同时也避免了程序之间的相互依赖而带来的不便。

例如,在使用计算机时,我们并不需要将计算机拆开了解它每个部件的具体用处,只需要按下电源键就能将计算机启动,这就体现了封装的好处。

3、多态
对象的状态是多变的。一个对象相对于同一个类的另一个对象来说,它们拥有的属性和方法虽然相同,但却可以有着不同的状态。另外,一个类可以派生出若干个子类,这些子类在保留了父对象的某些属性和方法的同时,也可以定义一些新的方法和属性,甚至于完全改写父类中的某些已有的方法。多态增强了软件的灵活性和重用性。

PHP class:定义类

1、变量:实现数据的复用
2、函数:实现代码块的复用
3、类:具有相同属性(变量)和方法(函数)的对象集合
4、对象:复合数据类型,可以储存且有权利对储存在其中的变量进行操作的一组函数
5、oop:单位是对象,对象是类的实例化的结果 instance
6、实现类的自动加载 前提必须满足psr-4规范:类文件名称和类同名

[修饰类的关键字] class 类名{
    类的成员属性和方法;
}

修饰类的关键字是一个可选参数,可以省略。我们通常使用下面这些关键字来修饰类:

abstract

抽象类或方法,被修饰为抽象类之后,类将不能被实例化,但可以被继承。如果类中有至少一个方法被声明为抽象的,那么这个类也必须声明为抽象的。继承一个抽象类的时候,子类必须重新定义父类中的所有抽象方法,而且这些方法的访问控制必须和父类中一样。

1、抽象方法
抽象方法是没有方法体的方法,所谓的没有方法体指的就是,在声明方法时候没有花括号{ }以及其中的内容,而是直接在方法名后加上分号结束。另外,在声明抽象方法时要使用“abstract”关键字修饰。格式如下所示:

abstract 访问权限修饰符 function 方法名1(参数列表);
abstract 访问权限修饰符 function 方法名2(参数列表);

abstract public function show();

2、抽象类的定义
只要一个类里面有一个方法是抽象方法,那么这个类就必须定义为抽象类,抽象类也需要使用“abstract”关键字来修饰,抽象类中也可以包含不是抽象方法的成员方法和成员属性,但访问权限不能是私有的(使用 private 关键字修饰),因为抽象类中的方法需要被子类继承。

1、abstract关键字用于定义抽象类
2、在抽象方法前面添加abstract关键字可以标明这个方法是抽象方法不需要具体实现{}
3、抽象类中可以包含普通的方法,有方法的具体实现
4、继承抽象类的关键字是extends
5、继承抽象类的子类需要实现抽象类中定义的抽象方法
6、抽象类不能被实例化,当子类继承抽象类的时候,所有的抽象的方法都必须定义

<?php

// 抽象类:可以为子类定义一些公共接口作为子类重写的模板来使用
// 抽象类可以有抽象方法,也可以有具体的方法 抽象类自身时不能被实例化的,需要被继承的子类来实例化对象
abstract class Person{
    public $name;
    protected $country;
    // 构造方法
    function __construct($name="admin",$country="China"){
        $this->name = $name;
        $this->country = $country;
    }
    // 抽象方法 没有方法体{}
    abstract public function eat();
    abstract protected function say();
    
    // 普通方法
    public function run(){
        echo "runing ……";
    }
}

// 通过子类继承来实现抽象类中的抽象方法
class Chinese extends Person{
    public function say(){
        echo $this->name.'是'.$this->country.'人,说'.$this->country.'话<br>';
    }
    public function eat(){
        echo "{$this->name}{$this->country}人,使用筷子吃饭<br>";
    }
}

$xiaom = new Chinese('小明','中国');
$xiaom->say();
$xiaom->eat();

class American extends Person{
    public function say(){
        echo $this->name.'是'.$this->country.'人,说'.$this->country.'话<br>';
    }
    public function eat(){
        echo "{$this->name}{$this->country}人,使用刀叉吃饭<br>";
    }
}
$jkx = new American('杰克逊','美国');
$jkx->say();
$jkx->eat();

在这里插入图片描述
抽象类就像是一个“半成品”的类,在抽象类中包含没有被实现的抽象方法,所以抽象类是不能被实例化的,即创建不了对象,也就不能直接使用它。

3、抽象类的使用
可以将抽象类看作是为它的子类定义公共接口,将它的操作(可能是部分也可能是全部)交给子类去实现。就是将抽象类作为子类重载的模板使用的,定义抽象类就相当于定义了一种规范,这种规范要求子类去遵守。

当子类继承抽象类以后,就必须把抽象类中的抽象方法按照子类自己的需要去实现。子类必须把父类中的抽象方法全部都实现,否则子类中还存在抽象方法,所以还是抽象类,也就不能实例化为对象。

<?php
abstract class Website{
    public $name = 'willem<br>';
    public $url = 'http://willem.cn<br>';
    abstract function title($title);
    abstract function output();
    abstract function run();
}

// 子类继承抽象类,来重写抽象方法
class SonDemo extends Website{
        
    public function title($title){
        echo $title;
    }
    public function output(){
        echo $this -> name.$this -> url;
    }
    
    // 实在用不到的可以将其函数体留空,但必须要把抽象方法全部都实现
    public function run(){
        
    }
}

$obj = new SonDemo();
$obj -> title("抽象类和抽象方法");
$obj -> output();

在这里插入图片描述

final:

使用 final 修饰的类不能被继承,而使用 final 修饰的方法不能在子类中重新定义。

注意:

一个类可以包含有属于自己的常量、变量(在类中称为“成员属性”或者“属性”)以及函数(在类中称为“成员方法”或者“方法”)。

self:: 的限制

使用 self:: 或者 CLASS 对当前类的静态引用,取决于定义当前方法所在的类:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();  // A
?>

举个栗子 (单例对象)

class Father {
    protected static $_instance = null;
    
    static public function getInstance()
    {
        if(self::$_instance === null)
        {
            //获取类的实例 self 始终永远和当前类进行绑定
            //1. self 始终永远和当前类进行绑定
            //2. self 在静态继承上下文中, 不能动态的识别或者设置静态成员的调用者
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}


class son1 extends Father 
{
    protected static $_instance = null;
}

class son2 extends Father
{
    protected static $_instance = null;
}

var_dump(Father::getInstance());
var_dump(Son1::getInstance());
var_dump(Son2::getInstance());
/* 
object(Father)#1 (0) { } 
object(Father)#1 (0) { } 
object(Father)#1 (0) { } 
*/

//使用self 实例化得到的都是Father类的同一个对象  (单例继承)

成员属性访问权限

说明public(默认)privateprotected
同一个类中访问
在子类中访问×
在类的外部访问××

static:静态成员,无需实例化对象,即可通过类名访问。

$this当前对象

在 PHP 面向对象编程中,对象一旦被创建,在对象中的每个成员方法里面都会存在一个特殊的对象引用“this ” 。 成员方法属于哪个对象 , “ this”。成员方法属于哪个对象,“this”。

成员方法属于哪个对象,“this”就代表哪个对象,与连接符->联合使用,专门用来完成对象内部成员之间的访问。

1、parent关键字可以用于调用父类中被子类重写了的方法

2、self关键字可以用于访问类自身的成员方法,静态成员和类常量;不能用于访问类自身的属性,使用常量的时候不需要在常量 const 名称前面添加 $ 符号。

3、static::关键字用于访问类自身定义的静态成员,访问静态属性时需要在属性前面添加$符号。

4、常量属性const不能使用对象访问,仅能使用类访问,在类本体内可以使用“self::常量名”,在类本体外可以使用“类名::常量名”。

示例1

<?php
class Person{
    public $name = 'shanghai';
    public $age = 20;
    protected static $tel;

    public function __construct($name,$age,$tel){
        $this->name = $name;
         $this->age = $age;
         self::$tel = $tel;
        echo "姓名:{$this->name},年龄:{$this->age},电话:". self::$tel;
    }

    public static function _setTel($_tel){
        self::$tel = $_tel;
        echo static::_getTel();
    }
    public static function _getTel(){
        return  self::$tel;
    }
}

class Son extends Person{
    private $sex;
    public static $email = "2602138376@qq.com";
    public function __construct($name,$age,$tel,$sex){
        $this->sex = $sex;
        parent::__construct($name,$age,$tel);
        echo ",性别:{$this->sex}";
    }

    public function getSex(){
        return $this->sex;
    }

    public static function _getTel(){
        echo "电话:".parent::_getTel();
        echo "邮箱:".self::$email;
    }
}



$p1 = new Person("shang",20,18949064166);
echo "<hr>";

echo $p1->name.'——'.$p1->age.'——';
echo Person::_getTel().'——';
Person::_setTel("15056825056");

echo "<hr>";

$s1 = new Son("孙小果",18,13096578824,"女");
echo "<hr>";

echo $s1->name.'——'.$s1->age;
echo "<hr>";

echo Son::_getTel();
echo "<hr>";

echo $s1->getSex();
Son::$email = "admin@php.cn";
echo Son::_getTel();

在这里插入图片描述

声明成员属性修饰关键字

在类中声明成员属性时,变量前面一定要使用一个关键字来修饰,例如 public、private,static 等,但这些关键字修饰的变量都具有一定的意义。

如果不需要有特定意义的修饰,可以使用“var”关键字,一旦成员属性有其他的关键字修饰就需要去掉“var”。

【示例】创建一个 Students 类并在类中声明一些成员属性,代码如下所示:

<?php
class Students{
	// 成员属性 一定要有访问修饰符 public protected private static
    public $name = 'zhang';
    public $age = 18;
    private $sex; // 抽象属性 null
    protected static $school;
}
?>

提示:

权限修饰符可以和定义静态变量的关键字 static 混合在一起使用,如上面代码中所示。

类中定义成员方法

在类中定义的函数被称为成员方法。函数和成员方法唯一的区别就是,函数实现的是某个独立的功能,而成员方法是实现类中的一个行为,是类的一部分。

可以在类中声明多个成员方法,成员方法的声明和函数的声明完全一样,只不过在声明成员方法时可以在function关键字的前面加一些访问权限修饰符来控制访问权限,例如 public、private、protected 等。

【示例】在上面示例中创建的 Students 类中创建一些成员方法。

<?php
class Students{
	// 成员属性 一定要有访问修饰符 public protected private static
    public $name = 'zhang';
    public $age = 18;
    private $sex; // 抽象属性 null
    protected static $school;
	
	// 成员实例方法
    public function Write(){
       echo '正在写字中……';
    }
    protected static function Read(){
		echo '正在读书中……';
    }
    function Listen(){
        echo '正在听力中……';
    }
}
?>

成员方法前面的权限修饰符可以省略,省略后默认权限为 public。

在类中成员属性和成员方法的声明都是可选的,可以同时存在,也可以单独存在,具体可以根据实际情况而定。

在 PHP7 中,引入了类型声明,我们可以为成员方法的形参和返回值声明类型,格式如下所示:

[权限修饰符] function 方法名 (类型 参数1, 类型 参数2, ..., 类型 参数n) : 返回值类型 {
    ... ...
}

PHP7 中支持声明的参数类型包括整型、浮点型、字符串型和布尔类型。

示例代码如下所示:

<?php
class Students{
    var $name;
    public $age;
    private $sex;
    public static $school;
    public function Write(string $a, int $b):bool{
       
    }
    protected static function Read(string $str):int{

    }
    function Listen(int $num):bool{

    }
}
?>

PHP new:实例化对象

将类实例化成对象非常容易,只需要使用 new 关键字并在后面加上一个和类名同名的方法即可。

当然如果在实例化对象时不需要为对象传递参数,在 new 关键字后面直接用类名称即可,不需要再加上括号。

对象的实例化格式如下:

变量名 = new 类名(参数数列表); 或 变量名 = new 类名;

参数说明如下:

变量名:

通过类所创建的一个对象的引用名称,可以通过这个名称来访问对象的成员;

new:关键字,表明要创建一个新的对象;

类名:表示新对象的类型;

参数列表:

指定类的构造方法用于初始化对象的值,如果类中没存定义构造函数,PHP - 会自动创建一个不带参数的默认构造函数。

【示例】创建一个类并将其实例化。

<?php
class Students
{

}
$person1 = new Students();
$person2 = new Students;
$person3 = new Students;
var_dump($person1);
echo '<br>';
var_dump($person2);
echo '<br>';
var_dump($person3);
?>

一个类可以实例化出多个对象,每个对象都是独立的。在上面的代码中通过 Students 类实例化出三个对象 person1 、 person1、person1、person2 和 $person3,相当于在内存中开辟了三份空间用于存放每个对象。

使用同一个类声明的多个对象之间是没有联系的,只能说明他们都是同一个类型,每个对象内部都有类中声明的成员属性和成员方法。就像独立的三个人,都有自己的姓名,性别和年龄的属性,每个人都有说话、吃饭和走路的方法。

对象的访问

对象中包含成员属性和成员方法,访问对象中的成员和访问数组中的元素类似,只能通过对象的引用来访问对象中的成员。

但还要使用一个特殊的运算符号->来完成对象成员的访问,访问对象中成员的语法格式如下所示:

变量名 =  new 类名(参数);   //实例化一个类
变量名 -> 成员属性 = 值;    //为成员属性赋值
变量名 -> 成员属性;        //直接获取成员属性的值
变量名 -> 成员方法();      //访问对象中的成员方法

下面通过一个示例来演示一下:

<?php
    class Website{
        public $name, $url, $title;
        public function demo(){
            echo '成员方法 demo';
        }
    }

    $student = new Website();
    $student -> name = 'php中文网';
    $student -> url = 'http://php.cn';
    $student -> title = '实例化对象';
    echo $student -> name.'<br>';
    echo $student -> url.'<br>';
    echo $student -> title.'<br>';
    $student -> demo();
?>

魔术方法

魔术方法作用
php面向对象编程(oop)基础知识

PHP的面向对象编程思想

php面向对象(OOP)编程完全教程

PHP面向对象(OOP)编程入门教程1.什么是面向对象?

面向对象基础

PHP面向对象OOP编程

(c)2006-2024 SYSTEM All Rights Reserved IT常识