Blogger Information
Blog 128
fans 9
comment 5
visits 241319
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
【PHP 面向对象】面向对象(OOP)编程知识点归纳总结(一)
 一纸荒凉* Armani
Original
2041 people have browsed it

一、面向对象的概念

面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持。如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的。下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法。

  我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境。和其他编程语言有所不同的是,在PHP中,操作数据库的 是一系列的具体功能函数(如果你不使用ODBC接口的话)。这样做虽然效率很高,但是封装却不够。如果有一个统一的数据库接口,那么我们就可以不对程序做 任何修改而适用于多种数据库,从而使程序的移植性和跨平台能力都大大提高。

对象的基本组成

  • 对象的组成元素:是对象的数据模型,用于描述对象的数据,又称为对象的属性,或者对象的成员变量.

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

对象特点

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

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

  • 对象是可以重复使用

类的概念

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

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

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

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

类的实例化

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

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

类的定义

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

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

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

二、OOP面向对象编程

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

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

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

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

1. PHP class:定义类

定义类

  • 变量:实现数据的复用

  • 函数:实现代码块的复用

  • 类:具有相同属性(变量)和方法(函数)的对象集合

  • 对象:复合数据类型,可以储存且有权利对储存在其中的变量进行操作的一组函数

  • oop:单位是对象,对象是类的实例化的结果 instance

  • 实现类的自动加载 前提必须满足psr-4规范:类文件名称和类同名

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

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

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

  • final:使用 final 修饰的类不能被继承,而使用 final 修饰的方法不能在子类中重新定义。
    注意:一个类可以包含有属于自己的常量、变量(在类中称为“成员属性”或者“属性”)以及函数(在类中称为“成员方法”或者“方法”)。

访问权限

常用访问权限修饰符及其含义如下所示:

  • public:公共的,在类的内部、子类中或者类的外部都可以使用;(不受限制)

  • protected:受保护的,在类的内部和子类中可以使用,但是不能被对象访问,只能通过封装的方式让对象访问;(可以被继承,但外部不能访问)

  • private:私有的,只能在类的内部使用,在类的外部或子类中都无法使用。(既不能继承也不能外部访问)

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

成员属性

在类中声明成员属性时,变量前面一定要使用一个关键字来修饰,例如 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{         }     } ?>

2. 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、$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();?>

$this当前对象

在 PHP 面向对象编程中,对象一旦被创建,在对象中的每个成员方法里面都会存在一个特殊的对象引用“$this”。成员方法属于哪个对象,“$this”就代表哪个对象,与连接符->联合使用,专门用来完成对象内部成员之间的访问。如下所示:

$this -> 成员属性;$this -> 成员方法(参数列表);

比如在 Website 类中有一个 $name 属性,我们可以在类中使用如下方法来访问 $name 这个成员属性:

$this -> name;

需要注意的是,在使用 $this 访问某个成员属性时,后面只需要跟属性的名称即可,不需要$符号。另外,$this 只能在对象中使用,其它地方不能使用 $this,而且不属于对象的东西 $this 也调用不了,可以说没有对象就没有 $this。

【示例】使用 $this 调用类中的属性和方法。

<?php    class Website{        public $name;        public function __construct($name){            $this -> name = $name;            $this -> name();        }        public function name(){            echo $this -> name.'<br>';            $this -> url();        }        public function url(){            echo 'http://php.cn<br>';            $this -> title();        }        public function title(){            echo 'PHP入门教程<br>';        }    }    $object = new Website('PHP中文网');?>

构造函数

魔术方法名称(双下划线开头):由系统调用 __set__get__call__callStatic__construct

__construct():构造函数/方法(构造器)

  • 对对的公共属性进行初始化赋值

  • 记录当前类被实例化的次数

构造函数(constructor method,也称为构造器)是类中的一种特殊函数,当使用 new 关键字实例化一个对象时,构造函数将会自动调用。

构造函数就是当对象被创建时,类中被自动调用的第一个函数,并且一个类中只能存在一个构造函数。和普通函数类似构造函数也可以带有参数,如果构造函数有参数的话,那么在实例化也需要传入对应的参数,例如new Students($name, $age),否则会报错。

<?php    class Website{        public $name, $url, $title;        private $price = 4900;        protected $num = 50;        public function __construct($name, $url, $title){            $this -> name  = $name;            $this -> url   = $url;            $this -> title = $title;            $this -> read();        }        public function read(){            echo $this -> name.'<br>';            echo $this -> url.'<br>';            echo $this -> title.'<br>';            echo $this -> price.'<br>';            echo $this -> num.'<br>';        }    }    $object = new Website('PHP中文网','http://php.cn/','构造函数');    /* 构造函数会在类实例化的时候,自动调用,所以我们的对象方法read也被调用了    PHP中文网    http://php.cn/    构造函数    4900    50    */    $object-> name = '百度一下';    $object-> url = 'http://baidu.com';    // 私有成员只能在本类的内部访问 ,通过实例化对象访问会报错    // $object-> price;    // protected 可以在本类内部和子类内部访问,同样实例对象不能访问    // $object-> num;    $object-> read();

3. PHP 类的自动加载机制

在使用面向对象模式开发程序时,通常大家习惯为每个类都创建一个单独的文件。这样会很容易实现对类进行复用,同时将来维护时也很便利,这也是面向对象程序设计的基本思想之一。当需要使用一个类时,只需要直接使用 include 或 require 将其包含进来即可,然后通过客户端代码加载这个类,然后进行实例化等一系列后续操作。

注意:类文件的名称需要与类名相同,另外一个类文件中只能定义一个类

Player.php

<?phpclass Player{    // 成员属性 一定要有访问修饰符 public protected private static    public $name = 'zhang';    public $height;    public $team;    // 受保护成员,仅限本类及子类中访问    protected $playerNum;    // 私有成员,仅限本类中使用    // 如何给私有成员赋值 1.可以通过构造函数 2.可以通过魔术方法    private $weight;    // 成员实例方法    public function jog(){        echo "{$this->name} is jogging";    }    // 魔术方法名称: 由系统调用    // __set __get __call __callStatic __construct    public function __construct($name,$height,$team){        // 对对象的公共属性进行初始化赋值        // 记录当前类被实例化的次数        $this->name = $name;        $this->height = $height;        $this->team = $team;    }}?>

client.php

<?php    require './Player.php';    require './Product.php';    $np1 = new Player('kebe','206cm','Laker');    echo $np1->name;    $np1->height = '198cm';    echo $np1->height;    $np1->jog();    // 私有成员只能在本类的内部访问 ,通过实例化对象访问会报错    // $object-> playerNum;    // protected 可以在本类内部和子类内部访问,同样实例对象不能访问    // $object-> weight;?>

spl_autoload_register()  函数

上述的方法虽然可以加载一个类,但如果一个页面需要使用多个类,就不得不在脚本页面开头编写一个长长的包含文件的列表。将本页面需要的类文件全部包含进来,这样处理不仅烦琐,而且容易出错。

autoload() 是系统函数,名称是固定的,而且该函数没有方法体,需要我们自定义方法体。另外,该函数是自动调用的,当我们 new 一个类时,如果当前源文件中找不到这个类,PHP 则会自动调用 autoload() 函数,并将类名传递给 __autoload() 函数。

autoload.php

<?php    // 注册类的自动加载器    spl_autoload_register(function ($class){        // 加载当前文件夹下的类        $file = './'.$class.'.php';        require $file;    });    $james = new Player('james','198cm','Laker');    echo $james->name."<br>";    echo $james->team."<br>";    echo $james->jog()."<br>";    $mobile = new Product("Redmi note9 pro",1599);    echo $mobile->show();?>

Product.php

<?php    class Product{        public $name;        public $price;        public function __construct($name,$price){            $this->name = $name;            $this->price = $price;        }        public function show(){            return "{$this->name},¥{$this->price}";        }    }?>

4. PHP static:类的静态成员

声明类的静态成员或静态方法为 static ,就可以不实例化类而直接访问,不能通过一个对象来访问其中的静态成员(静态方法除外)。静态成员属于类,不属于任何对象实例,但类的对象实例都能共享。

Static(静态)关键字

静态成员:定义时在访问控制关键字后添加static关键字即可(访问控制关键字:public. protected. private)

  • 静态属性用于保存类的公有数据,可以在不同对象间共享

  • 静态方法里面只能访问静态属性,不能访问非静态属性

  • 静态成员不需要实例化对象就可以访问

  • 类的内部可以通过 self:: 或 static:: 关键字访问自身静态成员,self::$属性 self::方法()

  • 通过 parent:: 关键字访问父类的静态成员,也可以通过子类::父类静态成员

  • 通过 类名:: 的方式在类的外部访问静态成员

<?php    // 类的静态成员 static    class User{        public static $name = 'zhang';        protected $_config = ['auth_on' => true,'auth_type => 1'];        // 认证方式 1 实时认证 2 登录认证        public static $nation = 'China';        private static $salary;        private static $count = 0;        public function __construct($name,$salary){            // 静态成员与类的实例对象无关,不能用$this来访问,他指向实例对象            // self::类的引用 访问静态成员            self::$name = $name;            self::$salary = $salary;            static::$count++;        }        public static function getCount(){            return sprintf("User类被实例化了%d次<br>",self::$count);        }        public static function getConfig(){            // 静态方法里面只能访问静态属性,不能访问非静态属性            // 原因:不管是静态成员还是静态方法,都是类级别存在的,随着类的加载而加载,优先于对象存在            // 非静态成员是对象级别的存在,静态方法中访问非静态成员属性,此时还不存在对象无法获取到            // return vsprintf("认证开关:%s,<br>认证类型:%d",$this->_config);            return vsprintf("认证开关:%s,<br>认证类型:%d",self::$_config);        }        public function getConfig2(){            return vsprintf("认证开关:%s,<br>认证类型:%d",$this->_config);        }    }    // 静态成员无需实例化调用,直接使用类名::成员    $user1 = new User('zhang',20000);    $user2 = new User('shuai',8000);    // 通过对象引用也可以访问静态成员方法,但不推荐这种写法    echo $user1->getCount();    // 但通过对象引用访问静态属性一定是不可以的,报错    // echo $user1->name;    // 直接使用类名::方法()调用    echo User::getCount();    // 静态属性可以在不同对象间共享 所以输出的是shuai    echo User::$name;   // echo User::getConfig();    echo $user2->getConfig2();?>

5. PHP extends:类的继承

面向对象编程(OOP)的一大好处就是,可以使用一个类继承另一个已有的类,被继承的类称为父类或基类,而继承这个父类的类称为子类。子类可以继承父类的方法和属性,因此通过继承可以提高代码的重用性,也可以提高软件的开发效率。

继承的好处:

  • 父类里面定义的类成员可以不用在子类中重复定义,节约了编程的时间和代价;

  • 同一个父类的子类拥有相同的父类定义的类成员,因此外部代码调用他们的时候可以一视同仁;

  • 子类可以修改和调用父类定义的类成员我们称为重写(Overwrite), 一旦子类修改了,就按照子类修改之后的功能执行;

  • 父类中有部分相同的属性和方法,子类可以增加父类之外的新功能,因此也可以将子类称为父类的“扩展”


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

子类:

  • 子类可以通过$this访问父类的属性

  • 子类的对象可以直接调用父类的方法和属性

  • PHP的单继承特性:类不允许同时继承多个父类(extends后面只能跟一个父类名称)

Product.php

<?php    class Product{        public $name;        public $price;        public function __construct($name,$price){            $this->name = $name;            $this->price = $price;        }        public function show(){            return "{$this->name},¥{$this->price}";        }    }?>

Goods.php

// 子类Goods类继承父类Productclass Goods extends Product{    // 属性扩展    private $num;    // 重写父类的构造器    public function __construct($name,$price,$num){        // parent::关键字调用父类的成员方法(构造方法)        parent::__construct($name,$price);        $this->num = $num;    }    // 重写父类的普通方法    public function show():string{        return parent::show().",数量:{$this->num} 个";    }    public function total(){        return "{$this->name},总计:".$this->price * $this->num."元";    }}

client.php

<?php spl_autoload_register(function ($class){       require './'.$class.'.php';    });    $good1 = new Goods('被子',266,8);    $good2 = new Goods('被罩',99,3);    echo $good1->show()."<br>";    echo $good1->total()."<br>";/* 被子,¥266,数量:8 个   被子,总计:2128元 */?>

数据访问总结

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

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

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

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

6. PHP instanceof:判断对象是否属于某个类

<?php spl_autoload_register(function ($class){       require './'.$class.'.php';    });    $good = new Goods('被子',266,8);    $james = new Player('james','198cm','Laker');//  instanceof 运算符,可以判断一个对象是否属于某一个类echo "<pre>";var_dump($good);var_dump($james);/*object(Goods)#2 (3) {  ["num":"Goods":private]=>  int(8)  ["name"]=>  string(6) "被子"  ["price"]=>  int(266)}object(Player)#3 (5) {  ["name"]=>  string(5) "james"  ["height"]=>  string(5) "198cm"  ["team"]=>  string(5) "Laker"  ["playerNum":protected]=>  NULL  ["weight":"Player":private]=>  NULL} */var_export($good instanceof Goods); // truevar_export($james instanceof Goods); // falsevar_export($james instanceof Player); // true?>

作业回顾:

  1. 类(对象抽象化的结果)与对象 (类实例化结果)

  2. 构造方法 3. 对象成员之间的内部访问 $this

  3. private仅限本类中使用 protected本类中,子类中使用

  4. 类的自动加载 spl_autoload_register

  5. 静态成员的访问 类的引用self::

  6. 类的继承 扩展 父类方法(魔术方法,普通方法)的重写 parent:: 调用父类成员

<?php    class Person{        public $name = 'zhangshuai';          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;        }    }?>
<?php    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;        }    }?>
<?php    spl_autoload_register(function ($class){       require './'.$class.'.php';    });    $p1 = new Person("zhang",20,18949064166);    echo $p1->name,$p1->age;    echo Person::_getTel();    Person::_setTel("15056825056");    echo "<hr>";    $s1 = new Son("孙小果",18,13096578824,"女");    echo $s1->name,$s1->age;    echo Son::_getTel();    echo $s1->getSex();    Son::$email = "admin@php.cn";    echo Son::_getTel();?>
Correcting teacher:灭绝师太灭绝师太

Correction status:qualified

Teacher's comments:bravo! 作业很详细~你是不是在看兄弟连的细说PHP啊?
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post