点我

后端基础【PHP面向对象】

类与对象概念

<?php

//创建一个对象
class cat {
    public $name;
    public $age;
    public $color;
 }
 //创建一个猫
$cat1= new cat;
$cat1->name="mingming";
$cat1->age=18;
$cat1->color="yellow";

 //再创建一个猫
$cat2= new cat;
 $cat2->name="honghong";
 $cat2->age=16;
 $cat2->color="pink";
 //输出两个猫的信息
if ($cat1->name="mingming"){
    echo $cat1->name."|".$cat1->age."|".$cat1->color.'<br/>';
 }if ($cat2->name="honghong"){
    echo $cat2->name."|".$cat2->age."|".$cat2->color;
 }

?>

invalid image(图片无法加载)

根据案例发现,类是抽象的,表示一类事物,对象是具体的,表示类的一个具体实例。类是对象的模板,对象是类的一个个具体实例。

类的创建格式:

class 类名{
成员属性(变量);
}

成员属性可以是基本数据类型也可以是复合数据类型(数组、对象)。

对象的创建格式:

$对象名 = new 类名();
或者
$对象名 = new 类名;

访问对象的属性
$对象名 -> 属性名;

构造函数

构造函数:在创建对象时直接给属性赋值。
构造函数是类的一种特殊函数,主要作用是完成对新对象的初始化。
两个特点:1.没有返回值;2.在创建一个类的对象时,系统会自动调用该类的构造函数完成对新对象的初始化。

案例

    <?php

    //创建一个对象
        class Person {
            public $name;
            public $age;

            public function __construct($name, $age) {
                $this->name = $name;
                $this->age = $age;
            }
        }
        $cat1 = new Person("xiaohong",5);
        echo $cat1->name;
        echo '<hr />';
        echo $cat1->age;

    ?>

invalid image(图片无法加载)

注意:构造函数在类中只能有一个,并且不能手动调用。它只能在创建新对象时自动调用。
代码中所使用的$this,它会指向当前对象,更深一步,就是这个对象的地址。哪个对象使用$this,就指向哪个对象的地址,$this不能再类外部使用。

析构函数

析构函数是另一种特殊的函数,用于在对象销毁时执行清理操作。
当对象不再被使用时,PHP会自动调用析构函数。与构造函数一样,析构函数的名称必须与类名相同,并且不带参数。

    <?php

    class MyClass {
        public function __construct() {
            echo 'Object created.';
        }

        public function __destruct() {
            echo 'Object destroyed.';
        }
    }
    $test = new MyClass;

    ?>

invalid image(图片无法加载)

在创建新的对象时,并输出一条消息“Object created.”。当脚本结束或对象不再被使用时,PHP将自动销毁该对象,并输出一条消息“Object destroyed.”。

需要注意的是,析构函数的执行时机不受程序员的控制。当对象不再被使用时,PHP会自动调用析构函数。
因此,析构函数主要用于执行清理操作,例如关闭数据库连接或释放资源等。

静态变量

<?php
class Child{
    public $name;
    public static $sums=0; //定义静态变量
  
    function __construct($name)
    {
        $this-> name = $name;
    }

    function JChild(){
        self::$sums += 1;
        echo $this-> name.'加入游戏';
        echo "<hr />";
    }
 }
 
    $child1=new Child("Ming");
    $child1->JChild();
    $child2=new Child("Zhang");
    $child2->JChild();
    $child3=new Child("Lin");
    $child3->JChild();
  
    echo '<br/>'."一共".Child::$sums."个小孩";
 ?>

invalid image(图片无法加载)

1、静态变量的修饰符为static;
2、静态变量的访问方式:
如果是在类的外部访问:类名::$类变量名
如果是在类的内部访问:类名::$类变量名 或者 self::$类变量名

注意:访问静态变量和是否创建对象无关,你不创建对象,也可以访问。访问静态变量,禁止使用$this,否则程序会报错。

静态方法

<?php
class Child{
    public $name;
    public static $sums=0; 
  
    function __construct($name)
    {
        $this-> name = $name;
    }

    static function JChild(){
        Child::$sums += 1;
  
    }

    function Join(){
        echo $this-> name.'加入游戏';
        echo "<hr />";
    }
 }
 
    $child1 = new Child("Ming");
    $child1->Join();
    $child1->JChild();
  
    $child2=new Child("Zhang");
    $child2->JChild();
    $child2->join();
    $child3=new Child("Lin");
    $child3->JChild();
    $child3->join();
  
    echo '<br/>'."一共".Child::$sums."个小孩";
 ?>

invalid image(图片无法加载)

静态方法和静态变量是对应的,只能调用静态变量,如果调用非静态变量它是会报错的。不过,反过来可以,即普通成员函数是可以调用静态变量的。原因是静态变量和静态方法都属于这个类,并且都是公开的。

封装

封装主要介绍三个修饰符,分别是public(公开的)、protected(受保护的)、private(私有的)

<?php
 class Person{  
    public $name;   
    protected $age;   
    private $wage; 
    public function __construct($name,$age,$wage){  //构造方法
           $this-> name = $name;
        $this-> age = $age;
        $this-> wage = $wage;
    }
 }
$p1=new Person("Ming",18,1000); //实例化对象
echo $p1->name;
echo $p1->age;  #进行了报错
echo $p1->wage; #进行了报错
?>

invalid image(图片无法加载)

protected(受保护的)与 private(私有的)这两个修饰符修饰的变量不能直接调用。要想调用,就需要写一个公开的方法,再直接调用方法就可以。

<?php
 class Person{  
    public $name;   
    protected $age;   
    private $wage; 
    public function __construct($name,$age,$wage){  //构造方法
           $this-> name = $name;
        $this-> age = $age;
        $this-> wage = $wage;
    }
    public function PersonAge(){
        echo $this->age;
        echo "<hr />";
    }
    public function PersonWage(){
        echo $this->wage;
        echo "<hr />";
    }

 }
$p1=new Person("Ming",18,1000); //实例化对象
echo $p1->name;
echo "<hr />";
echo $p1->PersonAge();
echo $p1->PersonWage();
?>

invalid image(图片无法加载)

你可能会有疑问,我们直接调就可以了,为什么要多走这一步?这是因为在方法里我们可以对变量进一步控制,比如加个范围,权限再控制得细一些等。也可以用另外一种方法,即PHP为我们提供的魔术方法:

__set()对protected或是private属性,进行赋值操作
__get()获取protected或是private属性的值

继承

<?php

// 父类
class Student{ 
    public $name;
    public $age;
    public $studentID;

    public function ShowInfo($name,$age){
        echo $this-> name = $name." | ".$this-> age = $age;
    }
 }

 // 子类 
class universityStudent extends Student{  
    public function study(){
        echo " 正在学习 ";
    }
 }

 $u1 = new universityStudent();
 $u1-> ShowInfo("Ming",22);
 $u1-> study();
 ?>

invalid image(图片无法加载)

子类可以使用父类的方法,这就解决了代码重复的问题。如果想要使用继承,关键字“extends”。所谓继承就是子类通过“extends”关键字,把父类的(public、protected)属性和(public、protected)方法继承下来。

还需注意,只能继承public、protected属性和public、protected方法,private的属性和方法只能在本类中使用。

在PHP中子类最多只能继承一个父类(指直接继承),在创建某个子类对象时,默认情况不会自动调用其父类的构造函数。

如果想调用父类的构造函数,可以通过在子类的代码中加入:“父类名::构造函数名”或者“parent::构造函数名”两种方法实现

<?php

// 父类
class Student{ 
    public $name;
    public $age;
    public $studentID;

   public function __construct(){
       echo "我是父类的构造函数";
   }

    public function ShowInfo($name,$age){
        echo $this-> name = $name." | ".$this-> age = $age;
    }
 }

 // 子类 
class universityStudent extends Student{  
    public function study(){
        echo " 正在学习 ";
    }

    public function __construct(){
        Student::__construct();
        echo " 我是子类的构造函数 "." <br/>";
    }
 }


 $u1 = new universityStudent();
 $u1-> ShowInfo("Ming",22);
 $u1-> study();
 ?>

invalid image(图片无法加载)

多态

函数重载

重载是类的多态的一种实现,是指一个标识符被用作多个函数名,并且能够通过参数个数或参数类型将这些同名的函数区分开,调用不发生混淆。

<?php
class A{  
    public $name;
    public $age;
    public function test1($a){ 
        echo "hello,123";
    }
    public function test2($a){ 
        echo "hello,456";
    }
    public function __call($name, $arguments) //定义call方法,会自动调用这个方法
    // __call为PHP的魔术方法

    //$name:被调用的方法的名称
    //$arguments:一个包含传递给方法参数的数组

    {
        var_dump($arguments);

         if($name=="test"){ 
            if(count($arguments)==1){
                $this->test1($arguments);
            }elseif (count($arguments)==2){
                $this->test2($arguments);
            }
        }
    }
 }
$a = new A(); 

$a-> test(1);
$a-> test(2,6);
?>

invalid image(图片无法加载)

注意:

    public function test(){
        echo "hello,123";
    }
    public function test($a){
        echo "hello,456";
    }


如果我们这么写,PHP会报错,其他的语言可以。

方法重写(覆盖)

假设我们设计一个类,提取一些相同的特征,设计成父类,并有一些函数,而子类想要完善父类的方法,只需要在子类中将方法的命名设为和父类相同,参数也完全相同就可以了。我们把它叫作方法重写(覆盖)。如果子类想要调用父类的方法,可以使用parent::方法名()。

子类方法不能缩小父类方法的访问权限,但可以扩大。

<?php

class A{
    public function Reset(){
        echo "父类的reset方法";
    }
}


class B extends A{
    public function Reset(){
        parent::Reset();
        echo '<hr />';
        echo "子类的reset方法";
    }
  
}

$obj = new B;
$obj-> reset();

?>

invalid image(图片无法加载)

抽象类

之所以设计抽象类,是为了快速开发,我们可能遇到这样的类,它是其他类的父类,但它本身并不需要实例化,主要是用于子类去继承。这样可以达到代码复用的目的,并且有利于项目设计者设计类。

抽象类格式:

abstract class 类名{
    abstract 修饰符 function 函数名(参数列表);//这里要注意,没有方法体。
}

抽象类不能被实例化。抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法。一旦类包含了abstract方法,则这个类必须声明为abstract。抽象方法不能有函数体。

如果一个类继承了某个抽象类,则它必须实现该抽象类的所有抽象方法(除非自己也声明为抽象类)。

接口

接口的存在是为了方便,也是为了规范。因为若要实现某个接口,就必须实现里面的所有方法。

<?php
 interface iTest{  //定义一个接口
    public function start();
    public function stop();
 }
 class camera implements iTest{
    public function start(){
        echo "计算机开始工作";
    }
    public function stop(){
        echo "计算机停止工作";
    }
 }
 class phone implements iTest{
    public function start(){
        echo "手机开始工作";
    }
    public function stop(){
        echo "手机停止工作";
    }
 }
 $c1=new camera();
 $c1->start();
 $c1->stop();
 echo "<br/>";
 $p1=new phone();
 $p1->start();
 $p1->stop();
 ?>

invalid image(图片无法加载)

接口比抽象类更抽象,所以,接口更不能被实例化了。接口中所有的方法都不能有主体。

一个类可以实现多个接口,用逗号隔开。

public class A implements 接口1,接口2{
 }

接口中可以有属性,但必须是常量,默认是public。接口中的方法必须是public,默认也是public。一个接口不能继承其他的类,但是可以继承别的接口。

interface 接口名 extends 接口1,接口2{
 }

如果我们希望某个类不被其他类继承,我们可以使用final关键字来修饰这个类。

final关键字通过在定义方法和常量之前加上 final 来防止被子类覆盖。 如果一个类被声明为 final,则不能被继承。

注意,如果我们用final来修饰某个类中的方法,则这个方法无法被重写。final也不能用来修饰成员属性。

分类: WEB安全

评论

-- 评论已关闭 --

目录