什么是面向对象?

面向对象介绍(英语:Object-oriented programming,缩写:OOP),专业术语我这里不多说,我们直接了断的来了解面向对象。

主要重点

  • 面向对象编程是一种计算机编程架构
  • 由单个能起到子程序作用的单元或对象组合而成
  • 每一个对象都是独一无二的
  • 对象是一个特定的事物,他的职能是完成特定功能
  • 对象是可以重复使用
  • 编程的时候数据结构(数据组织方式 )都通过对象的结构进行存储,使用属性和方法组织起来
  • 面向对象就是把生活中要解决的问题都用对象的方式进行存储--把所有的数据用属性、方法表现出来
  • 对象的描述方式更加贴合真实世界,有利于对大型业务的理解
  • 对象之间的互动是通过方法的调用完成互动
  • 对象只负责一项特定的职能(职能可大可小)
  • 外部世界可以看到对象的一些属性(并非全部)
  • 外部世界可以看到对象可以做某些事情(并非全部)

基本思路

  1. 识别对象
    任何实体都可以被识别为一个对象
  2. 识别对象的属性
    对象里面存储的数据被识别为属性

对于不同的业务逻辑,关注的数据不同,对象里面存储的属性也不同

  1. 识别对象的行为
    对象自己的属性数据的改变

对象外部的交互

面向对象都有哪些内容

定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。
命名是唯一性,但是可以使用命名空间来重复定义同样的名称
建议使用驼峰命名,这样代码的识别率和维护率会更高效

class MyClass() {
}

对象

是类的实例。

$Call = new MyClass();

成员变量

定义在类内部的变量。该变量的值对外是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可称为对象的属性。

class MyClass
{
    //成员变量
    var $title;
}

成员函数

定义在类的内部,可用于访问对象的数据。

class MyClass
{
    //成员变量
    var $title;

    //成员函数
    function setTitle($data){
        //变量 $this 代表自身的对象
        $this->title = $data;
    }
}

继承

继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
(白话讲就是在原有的类上加上一个类)
注意
如果你是自动加载类方式,那你需要加上命名空间和use
如果你是其他方式,你需要加入

require '';
//或者
require_once '';
//或者
include '';
//或者
include_once '';
//详细使用方法可以自行翻阅相关资料


Youclass 被继承的父类

namespace \user;
class YouClass
{
    
}

MyClass需要去继承的类

use \user;
class MyClass extends Youclass
{

}

父类

一个类被其他类继承,可将该类称为父类,或基类,或超类。
如上面的继承一样

Youclass 被继承的父类

namespace \user;
class YouClass
{
    
}

MyClass需要去继承的类

use \user;
class MyClass extends Youclass
{

}

子类

一个类继承其他类称为子类,也可称为派生类。

多态

多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
比如你的父类和子类的方法名称相同,那也没关系,我们可以看下面的代码就知道了

Youclass 被继承的父类

class YouClass
{
    var $title='这是一个标题文本';
    
    public function getTitle()
    {
        echo $this->title;
    }
}

MyClass需要去继承的类

include_once 'YouClass.php';
class MyClass extends YouClass
{
    // 重写父类实现
    public function getTitle()
    {
        echo '网页标题为:' . PHP_EOL;
        parent::getTitle(); // TODO: Change the autogenerated stub
    }
}

==PHP_EOL== 是自带的php换行

index.php调用

require 'MyClass.php';
$Call = new MyClass();
$Call->getTitle();

输出结果

网页标题为:
这是一个标题文本

我们在子类的 getTitle 方法中,先打印了一段提示文本,然后和构造函数一样,通过

parent::getTitle

调用父类的同名方法,因为所有的流程基本都是一样的。
重要的是parent::

包含了第一行提示文本,所以,调用的是子类的方法而不是父类的。

重载

简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
属性重载

__set      赋值
__get      读取
__isset    判断是否存在
__unset    销毁

class Person {
    public $name = '张三';

    protected $age = 18;

    public function __get($n) {
        //echo '试图读取不可访问的属性'.$n;
        return $this -> age;
    }

    public function __set($n,$v) {
        //echo '试图设置不可访问的属性'.$n;
        $this -> $n = $v;
    }
    public function __isset($n) {
        echo '判断不可访问的属性'.$n.'是否存在';
    }
    public function __unset($n) {
        echo '销毁不可访问的属性'.$n;
    }
}
$Call = new Person();

// 读取

//echo $Call -> age;
//echo $Call -> xxx;

// 设置

//$Call -> age = 30;
//echo $Call -> age;

// 判断存在与否

isset($Call -> age);

// 销毁
unset($Call -> age);

方法重载

__call         调用不可访问的普通方法
__callStatic   调用不可访问的静态方法

class Person {

    protected function func($n) {
        echo '这是一个不可访问的方法';
        echo '参数有'.$n;
    }

    protected static function fun2() {
        echo '受保护的静态方法';
    }

    public function __call($function_name,$args) {
        echo '触发了不可访问的方法';
        var_dump($function_name);
        var_dump($args);
    }

    public static function __callStatic($function_name,$args)   {
        echo '触发了不可访问jing tai方法,静态!!!!';
        var_dump($function_name);
        var_dump($args);
    }
}
// 实例化
$Call = new Person();
$Call -> func([1,2,3]);
$Call -> func2([1,2,3]);

抽象性

抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。

抽象类指的是包含抽象方法的类,而抽象方法是通过 abstract 关键字修饰的方法,抽象方法只是一个方法声明,不能有具体实现:

abstract public function drive();

只要某个类包含了至少一个抽象方法,它就是抽象类,抽象类也需要通过 abstract 关键字修饰

abstract class Car
{
    abstract public function drive();
}

如果没有通过 abstract 关键字修饰,会报错

封装

封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。

构造函数

主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
void __construct ([ mixed $args [, $... ]] )

class MyClass
{
    //成员变量
    var $title;
    
    //构造函数
    public function __construct(){
        $this->title='这个变量内容';
    }
}

析构函数

析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
void __destruct ( void )

class MyDestructableClass {
   function __construct() {
       print "构造函数\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "销毁 " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
构造函数
销毁 MyDestructableClass

你还知道__toString()吗?

__toString() 是魔术方法的一种,具体用途是当一个对象被当作字符串对待的时候,会触发这个魔术方法

class Account {
    public $user = 1;
    private $pwd = 2;

    //自定义的格式化输出方法
    public function __toString() {
        return "当前对象的用户名是$this->user,密码是$this->user";
    }
}
当前对象的用户名是1,密码是1

若是使用var_dump($a)的运行结果为

object(Account)#1 (2) { 
["user"]=> int(1) 
["pwd":"Account":private]=> int(2) 
} 

运行这段代码发现,使用toString方法后,输出结果是可定制的,更易于理解。实际上,toString方法也是一种序列化,PHP自带的serialize和unserialize也是进行序列化的,可是这组函数序列化时会产生一些无用信息,如属性字符串长度,形成存储空间的额浪费。所以,能够实现本身的序列化和反序列化方法,或者json_encode/json_decode也是一个不错的选择。

为何直接echo一个对象就会报语法错误,而若是这个对象实现了__toString()方法后就能够直接输出呢?
原因很简单,echo原本能够打印一个对象,并且实现了这个接口,可是PHP对其作了限制,只有实现toString后才容许使用

结尾

好久没更新博客了,需要来活跃活跃,但是呢,讲的太深,别人也不懂,那就只能写基础,帮助大家巩固一下面向对象的一些知识。

文章目录