欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【PHP7 面向对象 笔记整理一】构造方法和析构方法

程序员文章站 2024-03-17 16:30:34
...

  本节主要讲解 PHP面向对象中的 魔术方法 中的其中两种,构造方法析构方法,主要从以下三部分总结:

一、__construct 构造方法

二、__destruct 析构方法

三、构造方法 和 析构方法 【综合练习】



一、 __construct 构造方法

1) 格式:

修饰符 function __construct()
{
    方法体
}

实例1:构造方法执行

class cc
{
    public $name = '串串';
    public $age = 18;

    public function __construct()
    {
        echo "预备工作,准备干掉串串<br>";
    }
}

// 实例化
$a = new cc;

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

2) 特性

  ① 在实例化的瞬间,自动触发;

  ② 无返回值;

  ③ public 可以省略;

  ④ 构造方式 不允许重复。

3) 调用构造方法的两种方式:

① 自动调用

// 实例化
$a = new cc;

② 手动调用

$a->__construct();

4) 作用:

​ 常用于做 赋初始值 (完成一些对象的初始化工作)

实例2:构造方法 赋初始值

class cc
{
    public $name;
    public $age;

    // 此处的 $name是形参,与属性$name无关
    public function __construct($name, $age)
    {
        echo "预备工作,准备干掉串串";

        // 将 形参 给了 属性
        $this->name = $name;
        var_dump($this->name);

        echo "<hr>";
    }

    public function test1()
    {
        echo '<br>测试1<br>';
        echo $this->name;
        echo "<hr>";
        return $this;
    }
}

// 实例化
$a = new cc('串串', 18);
echo $a->name;
echo "<hr>";

$a->test1();

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

如何 将两个变量中的方法通用?

答案: 将 变量 变成 属性

class cc
{
    public $name;
    public $age;

    // 此处的 $name 与属性 $name无关
    public function __construct($name, $age)
    {
        // 将 形参 给了 属性
        $this->name = $name;
        $this->age = $age;
    }

    public function test1()
    {
        // 如何 将两个方法中的 变量通用?
        // 答案:将 变量 变成 属性
        echo $this->name;
        echo $this->age;
    }
}

实例3:如何 将两个方法中的 变量通用?

class cc
{
    public $name;
    public $age;

    // 此处的 $name是形参,与属性 $name 无关
    public function __construct($name, $age)
    {
        echo "预备工作,准备干掉串串<br>";

        // 将 形参 给了 属性
        $this->name = $name;
        var_dump($this->name); echo "<br>";
        $this->age = $age;
        var_dump($age); 

        echo "<hr>";
    }

    public function test1()
    {
        echo "<br>测试1<br>";
        echo $this->name;
        echo "<br>";
        // 如何 将两个方法中的变量 通用?
        // 答案:将变量 变成 属性 
        echo $this->age;
        echo "<br>";
        return $this;
    }
}

// 实例化
$a = new cc('串串', 18);
echo $a->name;
echo "<hr>";

$a->test1();

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法
注意事项:

​  没有构造方式时,如果方法名 和 类名相同,自动调用方法;有构造方法时,方法名不会自动调用。【建议:尽量方法名和类名不要相同】

实例4: 无构造方法时

class cc
{
    public $name;
    public $age;

    public function cc()
    {
        echo "测试1<br>";
    }
}

$a = new cc();
echo 222;

运行结果:可以看到,都没有构造方法的时候,类名方法名 相同会报错。

【PHP7 面向对象 笔记整理一】构造方法和析构方法

实例5:有构造方法时

class cc
{
    public $name;
    public $age;

    public function __construct()
    {
        echo "预备工作,准备干掉串串<br>";
    }

    public function cc()
    {
        echo "测试1<br>";
    }
}

$a = new cc();
echo 222;

运行结果:有构造方法时,方法名不会被调用,但是尽量不要让方法名和类名同名,否则没有构造方法的时候,是会报错的。

【PHP7 面向对象 笔记整理一】构造方法和析构方法
不成文规定:

​  构造方法写在属性的最后面,方法的最前面。

class cc
{
    // 属性
    public $name;
    public $age;

    // 构造方法
    public function __construct()
    {
        echo "构造方法";
    }

    // 方法
    public function test()
    {
        echo "测试1<br>";
    }
}


二、__destruct 析构方法

  ​相当于 遗嘱 die()

​  在整个程序结束之前执行

1) 格式:

public function __destruct()
{
    方法体
}

2) 特性:

① 当对象被销毁时,自动调用;

  • 程序自然结束时,对象会自动消失;
  • 对象变量 被 unset;
  • 对象变量 被覆盖

② 不能有参数;

实例1:程序自然结束时

class cc
{
    public $name;
    public $age;

    public function test1()
    {
        echo "测试1<br>";
    }

    public function __destruct()
    {
        echo "老母鸡";
    }
}

$a = new cc;

$a->test1();

echo "小母鸡<br>";

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

实例2:对象变量 被 unset时

class cc
{
    public $name;
    public $age;

    public function test1()
    {
        echo "测试1<br>";
    }

    public function __destruct()
    {
        echo "老母鸡<br>";
    }
}

$a = new cc;
$a->test1();

unset($a);

echo "小母鸡<br>";

运行结果:
【PHP7 面向对象 笔记整理一】构造方法和析构方法
实例3:对象变量 被覆盖

class cc
{
    public $name;
    public $age;

    public function test1()
    {
        echo "测试1<br>";
    }

    public function __destruct()
    {
        echo "老母鸡<br>";
    }
}

$a = new cc;
$a->name;

$a = 10;

echo "小母鸡<br>";

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

3) 作用:

  ​给对象写临时前的遗嘱。(即对象在销毁之前的清理工作)

不成文规定:

​  析构方法 一般写在方法的最后面

class cc
{
    public $name;
    public $age;

    // 方法
    public function test1()
    {
        echo "测试1<br>";
    }

    // 析构方法
    public function __destruct()
    {
        echo "老母鸡<br>";
    }
}


三、构造方法 和 析构方法 【综合练习】

实例1: 构造方法 和 析构方法 (综合练习1)

class test
{
    // 构造方法
    public function __construct()
    {
        static $x = 0;
        $x++;
        echo $x."<br>";
    }

    // 方法
    public function hello()
    {
        echo "母鸡<br>";
    }

    // 析构方法
    public function __destruct()
    {
        static $y = 10;
        $y++;
        echo $y."<br>";
    }
}

$a = new test; // 1 
$a->hello(); // 母鸡 
$a = new test; // 2 11 12

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法
分析结果:

  ① $a = new test; 先 执行构造方法,输出 1,由于后面还有代码,因此不会 执行析构方法;

  ② $a->hello(); 输出 母鸡;

  ③ $a = new test; 等号的优先级是先做右边,因此先执行右边的 new test,new 的一瞬间,再次执行 构造方法,由于构造方法中,已经输出1,再次执行 输出 2

​  ④ 再执行左边,此时第一个 $a 被覆盖,因此触发 第一次 new test 的析构方法,输出 11;(执行 第一个 new test的析构)

​  ⑤ 由于下面再没有代码执行,因此触发第二次析构方法(此时已经输出为11),再次执行 输出 12 (执行第二个 new test的析构)

执行步骤归纳:

​  为了方便归纳总结:现将代码继续排序:

   a. $a = new test;

   b. $a->hello();

   c. $a = new test;

  1) a 中的 构造方法,输出 1
  2) b 中的 方法,输出 母鸡
  3) c 中的 构造方法, 输出 2;(执行的是 c中的右边)
  4) a 中的 析构方法, 输出 11;(由于c 中的 $a覆盖了 a中的$a,因此触发a 中的析构方法)
  5) c 中的 析构方法,输出12.

实例2:构造方法 和 析构方法 (综合练习2)

class test
{
    // 构造方法
    public function __construct()
    {
        static $x = 0;
        $x++;
        echo $x."<br>";
    }

    // 方法
    public function hello()
    {
        echo "母鸡<br>";
    }

    // 析构方法
    public function __destruct()
    {
        static $y = 10;
        $y++;
        echo $y."<br>";
    }
}

$a = new test;
$a->hello();
$b = new test;

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法
执行步骤归纳:

  为了方便归纳总结:现将代码继续排序:

   a. $a = new test;

   ​b. $a->hello();

   c. $b = new test;

  1)a 中的 构造方法,输出1
  2) b 中的 方法, 输出母鸡
  3) c 中的 构造方法,输出2;(等号的优先级,先执行右边,实例化的同时,触发 构造方法)
  4) c 中的 析构方法,输出11;(等号的左边,由于以下没有代码,触发 c中的 析构方法,根据 数据结构中的 “后进先出” 执行 c中的析构方法)
  5)a 中的 析构方法, 输出12.

注:虽然和先前的执行结果是一样的,但是 原理不同,遵循的是 数据结构中的堆栈思想(先进后出).

实例3:构造方法 和 析构方法 (综合练习3)

class test
{
    // 构造方法
    public function __construct()
    {
        static $x = 0;
        $x++;
        echo $x."<br>";
    }

    // 方法
    public function hello()
    {
        echo "母鸡<br>";
    }

    // 析构方法
    public function __destruct()
    {
        static $y = 10;
        $y++;
        echo $y."<br>";
    }
}

$a = new test;
$a->hello();
$b = new test;
$a->hello();
$b = new test;

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

分析结果:

​  ① $a = new test; (实例化的时候,执行 构造方法,输出 1),由于下面还有代码,则继续执行;

​  ② $a->hello(); 输出 母鸡

  ③ $b = new test; (根据等号的优先级,先执行左边,实例化的时候,再次执行 构造方法 ,先前输出1,此时输出 2),由于下面还有代码,则继续执行;

  ④ $a->hello(); 输出 母鸡

​  ⑤ $b = new test; (根据等号的优先级,先执行左边,实例化的时候,再次执行 构造方法,先前输出3, 此时输出 3);

​  ⑥ 再执行右边,由于 此处的 $b,覆盖了 ③ 中的 $b,因此触发了 ③中的析构方法,输出 ③中的 $b, 输出为 11;

​  ⑦ 由于⑤ 以下已经没有代码,因此触发了⑤中的 析构方法,由于先前输出 11,此处输出 12

​  ⑧ 最后触发① 中$a的 析构方法,先前输出12, 此处 输出 13.

执行步骤归纳:

​  为了方便归纳总结:现将代码继续排序:

​   a. $a = new test;

   b. $a->hello();

   c. $b = new test;

   d. $a->hello();

   e. $b = new test;

  1) a 中的 构造方法,输出1
  2) b 中的 方法,输出 母鸡
  3) c 中的 构造方法,输出 2
  4) d 中的 方法, 输出 母鸡
  5) e 中的 构造方法,输出 3
  6) c 中的 析构方法, 输出 11;(由于e中的 $b覆盖了 c中的$b,触发了 c中的析构方法)
  7) e 中的 析构方法, 输出 12;(由于e下面没有代码执行了)
  8) a 中的 析构方法,输出 13

实例4:构造方法 和 析构方法(综合练习4)

class test
{
    // 构造方法
    public function __construct()
    {
        static $x = 0;
        $x++;
        echo $x."<br>";
    }

    // 方法
    public function hello()
    {
        echo "母鸡<br>";
    }

    // 析构方法
    public function __destruct()
    {
        static $y = 10;
        $y++;
        echo $y."<br>";
    }
}

$a = new test;
$a->hello();
$a = new test;
$a->hello();
$a = new test;

运行结果:

【PHP7 面向对象 笔记整理一】构造方法和析构方法

分析结果:

  ① $a = new test;(实例化的时候,触发 构造方法,输出1

  ② $a->hello(); (输出母鸡

  ③ $a = new test;(第二个 new test),根据等号的优先级,先执行右边;当实例化的时候,会触发 构造方法,先前输出1,此处输出2

  ④ 执行 第二个 new test的左边(即第二个$a),由于会把 第一个\$a覆盖,会触发 第一个\$a的 析构方法,输出11

  ⑤ $a = hello(); (输出母鸡

  ⑥ $a = new test(第三个 new test),根据等号的优先级,先执行右边;当实例化的时候,会触发 构造方法,先前输出2,此处输出3

  ⑦ 执行 第三个new test的左边(即第三个$a),由于会把 第二个\$a覆盖,会触发 第二个\$a的 析构方法,先前输出11,此处输出12

  ⑧ 由于 第三个 new test下面再无代码,因此会触发 第三个$a的 析构方法,先前输出12,此处输出13.

执行步骤归纳:

  为了方便归纳总结:现将代码继续排序:

   a. $a = new test;

   b. $a->hello();

   c. $a = new test;

​   d. $a->hello();

​   e. $a = new test;

  1)a 中的 构造方法,输出1
  
  2) b 中的 方法,输出母鸡
  
  3) c 中的 构造方法, 输出2;(等号的优先级,先执行右边,会触发 构造方法)

  4) a 中的 析构方法,输出11;(执行c中的左边,左边的$a 会覆盖 a中的 $a,因此触发 a中的析构方法)

  5) d 中的 方法, 输出母鸡

  6) e 中的 构造方法,输出3;(等号的优先级,先执行右边,会触发 构造方法)

  7) c 中的 析构方法, 输出12;(执行e中的左边,左边的$a 会覆盖 c中的 $a,因此触发 c中的析构方法)

  8) e 中的 析构方法,输出13;(e下面再无代码,会触发 e中的析构方法)

以上只是我学习过程中涉及到的,有缺漏处,之后补充。