php基础巩固加强(五)

面向对象

面向对象不是一种技术,也是一种思想,从面向过程进化而来。

面向对象的核心思想:不是简单的将某个功能封装成函数,还要将相似功能的函数所调用的主体也进行封装,实现某个主体拥有多个功能。在使用的过程中,先得到对应的主体,然后使用主体去应用其对应的功能。

面向对象与面向过程对比

1.       都是实现模块化编程,面向对象的模块化更深。

2.       面向对象更加贴近现实生活。

3.       从开发难度上讲,面向对象比面向过程要复杂的多。

4.       从维护角度来讲,现象对象要比面向过程简单

面向过程是针对功能,面向对象是针对功能操作的主体

以前写代码的方式:碰到功能马上写函数

以后写代码的方式:碰到功能,先找到会要去调用该功能的实体(主体),再把主体给封装后,再实现功能。

面向对象的几个基本概念

类:类就是实体(主体),指的是把具有一些共性的东西,把共性抽离出来变成计算机可以识别的代码。

对象:属于某个类的一个具体的实例

实例化:从类创建对象的过程

类 –》实例化—》对象

类:也是通过程序语言定义出来的结构

语法: class 类名

{

    //类成员

}

实例化:通过类得到对象的过程

语法:new 类名[()]

对象:是通过类实例化最终得到的结果

变量 = new 类名

类的定义和实例化demo如下:

//定义类
class Person
{
    
}

//实例化对象
$person1 = new Person;
var_dump($person1);

/*输出如下:
object(Person)#1 (0) { }

object:对象数据类型(即$person1的数据类型是对象(object)类型)
Person:当前对象属于某个类(即当前对象$person1属于Person类)
#1:对象的编号 如果编号相同,是同一个对象
0:类成员的个数(属性)对象拥有个数
{}:对象里所拥有的具体属性
*/

类成员

类成员:类里面所能定义的内容(类的属性和方法统称为类成员)

类中可以定义:属性,方法,类常量

属性:定义在类里面的变量,因为在类中所以需要使用修饰符


修饰符修饰属性

demo:

//定义类
class Person
{
    //类成员
    
    //属性
    var $height = 175; //var是php4以前对类中属性的访问修饰符
    var $age = 20;

    //echo 'hello world'; //错误的,类中只能定义三类类成员
}

访问修饰限定符:限定属性可以被访问的范围(区域)

var:老版本的面向对象的属性修饰符,表示在类的内部和类的外部都能够被访问

public:公共的,与var的功能是一样的

private:私有的,只能在类的内部被使用(函数的局部变量)

protected:受保护的,只能在类的内部被使用,可以被继承。(在没有讲面向对象的继承之前,protected与private是一样的)

//定义类
class Person
{
    //类成员

    //属性
    var $height = 175; //var是php4以前对类中属性的访问修饰符
    var $age = 20;

    public $name;  //Person类的属性$name
    private $salary;  //Person类的属性$salary
    protected $money;  //Person类的属性$money
    
}

如何访问类中的属性呢?

属性都是通过对象去进行访问

语法:对象->属性名字

私有不能在外部访问

访问类中的属性demo如下:

//定义类
class Person
{
    //类成员

    //属性
    var $height = 175; //var是php4以前对类中属性的访问修饰符
    var $age = 20;

    public $name = '和其正';
    private $salary = 500;
    protected $money = 5000;

}

//实例化对象
$person1 = new Person;

//访问对象的属性
//所有的以下访问都是在类的外部进行访问
//var_dump($person1->name); //访问姓名,public可以在类的外部访问 输出:和其正
//var_dump($person1->height);  //访问身高,可以访问因为var就是public 输出:175
//var_dump($person1->salary);  //访问工资  报错:私有的(private)不能在类的外部访问
//var_dump($person1->money);   //访问财产  报错:受保护的(protected)同样也不能在类的外部进行访问

方法:定义在类里面的函数

demo:

//定义类
class Person
{
    //类成员

    //属性
    var $height = 175; //var是php4以前对类中属性的访问修饰符
    var $age = 20;

    public $name = '和其正';
    private $salary = 500;
    protected $money = 5000;

    //定义方法
    private function makeMoney($money)
    {
        echo $money;
    }

}

如何调用方法?

对象调用方法

语法:对象->方法名字(参数列表);

demo如下:

//定义类
class Person
{
    //类成员

    //属性
    var $height = 175; //var是php4以前对类中属性的访问修饰符
    var $age = 20;

    public $name = '和其正';
    private $salary = 500;
    protected $money = 5000;

    //定义方法(方法前面没有加访问修饰符 即使用的是默认访问修饰符:public)
    function makeMoney($money)
    {
        echo $money;
    }

}

//实例化对象
$person1 = new Person;  //实例化对象的时候类后面可以没有小括号,如果实例化对象的时候需要传入参数那么小括号必须写上并传入参数
$person1->makeMoney(17000); //输出:17000

方法也可以使用访问修饰限定符:public,private,protected,默认是public

限制访问与属性的限制是一样的(即 如果类中的方法使用的访问修饰符是protected或private那么在类的外部调用此方法的时候会报错,因为只有public修饰的方法才能在类的外部访问)

类常量

类常量:定义在类里面的常量

语法:const 常量名字 = 值

demo:

//定义类
class Person
{
    //类常量
    const PI = 3.1415926;

}

//访问类常量(可直接通过类名::常量名 进行访问) ::这个东西叫:范围解析操作符,又名域运算符 以后在讲解具体干嘛用的
echo Person::PI; //输出: 3.1415926

对属性进行赋值

语法:对象->属性 = 值;

demo如下:

//类属性操作
class Person
{
    //定义属性
    public $name;
    private $age;

    //定义方法
    public function getAge()
    {
        //
    }
}

//实例化得到对象
$person = new Person();

//访问name属性,并给name属性赋值
$person->name = 'Pepsi';

//输出name属性的值
echo $person->name; //输出:Pepsi

私有属性访问

私有属性只能在类中被访问,而类里只有三种成员:属性,方法和常量,只有方法可以帮助对象实现私有属性的访问。

在类中class里面(方法里面),可以使用$this代表当前调用该方法的对象

demo如下:

//类属性操作
class Person
{
    //定义属性
    public $name;
    private $age;

    //定义方法
    public function getAge()
    {
        //访问私有属性age
        //var_dump($this);

        //使用$this代表当前对象
        echo $this->age;
    }

    public function setAge($ages)
    {
        //通过传入一个$ages参数给当前对象的age属性赋值
        $this->age = $ages;
    }
}

//实例化得到对象
$person = new Person();

$person->setAge(18);   //setAge()方法里的$this表示$person这个对象
echo $person->getAge(); //输出:18,getAge()方法里的$this表示$person这个对象

$person1 = new Person();

$person1->setAge(20);  //setAge()方法里的$this表示$person1这个对象
echo $person1->getAge(); //输出:20,getAge()方法里的$this表示$person1这个对象

总结:类里面的$this 代表的就是你new一个类之后产生的那个对象。比如说:$object = new class_name(); 即,class_name()类里面的$this就是$object

类的外部访问类的内部的私有方法

demo如下:

//类属性操作
class Person
{
    //定义属性
    public $name;
    private $age;

    //私有方法
    private function getName()
    {
        //获取当前对象的name属性
        echo $this->name;
    }

    public function getGetName()
    {
        $this->getName();
    }
}

//实例化得到对象
$person = new Person();
$person->name = '张无忌';

$person->getGetName(); //输出:张无忌

/*
我们要在类的外边访问类里面的一个私有(private)方法,但是大家都知道,private修饰的属性和方法只能在类的内部进行访问和操作,
如何在类的外部访问类的内部的私有方法呢?比如上面我们可以在类的内部定义一个公共(public)的getGetName()方法。而这里面我们就
可以使用$this->getName()在调用私有方法。从而达到类的外部访问私有方法或者属性。
*/

类名的命名规则

1.不需要$符号

2.可以使用字母,下划线和数字组成,通常都是使用字母

3.类名不区分大小写,建议我们自己要区分大小写

4.类名通常使用驼峰法命名(个人习惯,类名的第一个字母大写)

魔术方法

魔术方法:系统已经定义好,但是需要用户在类里面显示的写出来才会被执行的方法。一旦定义了魔术方法,

那么在某些特定的情况下会自动触发。

构造方法

在创建对象之后,会自动被对象调用的方法

语法:__construct()

构造方法demo如下:

//定义类
class Person
{
    //属性
    public $name;
    public $height;
    public $age;
    private $salary;

    //定义方法初始化属性
    /*
    public function setProperty($name,$height,$age,$salary){
        //对属性进行赋值
        $this->name = $name;
        $this->height = $height;
        $this->age = $age;
        $this->salary = $salary;
    }
    */

    //构造方法
    public function __construct($name,$height,$age,$salary = 1000)
    {
        //对属性进行赋值
        $this->name = $name;
        $this->height = $height;
        $this->age = $age;
        $this->salary = $salary;
        echo __METHOD__;   //输出:Person::__construct
    }

    //php低版本面向对象的构造方法
    //兼容低版本的构造方法
    public function Person($name,$height,$age,$salary = 1000)
    {
        //对属性进行赋值
        $this->__construct($name,$height,$age,$salary = 1000);
    }

}

//实例化
//$person = new Person(); //希望person对象的属性都已经被赋值
//var_dump($person);

//调用初始化方法
//$person->setProperty('张无忌',173,28,20000);
//var_dump($person);

//实例化一个对象
$person = new Person('敏敏特穆尔',168,18,100000);
//1.   $person = new Person;
//2.   $person->__construct('敏敏特穆尔',168,18,100000)
//类后面的括号实际上是为构造方法准备

//使用构造方法 的默认值(传入三个参数,第四个参数不传表示使用第四个参数的默认值)
$person1 = new Person('灭绝师太',165,58);

总结:构造方法就是为了初始化对象的属性。

析构方法

当 当前对象被销毁的时候,当前对象会自动调用的一个方法

语法:__destruct();

析构方法触发条件以及demo如下:

//定义类
class Person
{
    //属性
    public $name;
    public $height;
    public $age;
    private $salary;

    //构造方法
    public function __construct($name,$height,$age,$salary = 1000)
    {
        //对属性进行赋值
        $this->name = $name;
        $this->height = $height;
        $this->age = $age;
        $this->salary = $salary;
        echo __METHOD__."<br/>";  //输出:Person::__construct
    }

    //析构方法
    public function __destruct()
    {
        echo __METHOD__;
    }
}

/*
当创建对象(new一个类的时候)的时候,会自动触发__construct()构造方法,当脚本运行结束后又会自动触发__destruct()析构方法,
为什么会又会自动触发析构方法呢?因为脚本执行完毕之后,会释放所有变量(包括当前对象 即$person也要被释放(销毁)),一旦对象被释放
就会自动调用对象对应的析构方法,所以 以下new一个对象的时候会输出Person::__construct和Person::__destruct
*/
$person = new Person('敏敏特穆尔',168,18,100000); //输出:Person::__construct和Person::__destruct

//析构方法的作用:释放资源(内存等)

/*让析构方法执行的方式(即触发析构方法的条件)有以下几种
1.脚本执行结束析构方法自动被执行
2.unset主动释放变量所占用的内存(对象释放)  unset($person);
3.让变量等于空(对变量重新赋值) $person = null;
*/

//大部分情况下我们不会去写析构方法,因为php有一个非常良好的垃圾回收机制,一旦脚本之行结束 内存都会被自动回收

对象传值

对象传值之间的证明如下:

//定义一个类
class Person
{
    //属性
    public $name;
    private $age;

    //构造方法
    public function __construct($name,$age)
    {
        $this->name = $name;
        $this->age  = $age;
    }
}


$person1 = new Person('韩顺平',35); //实例化对象

echo '<pre>';

$person2 = $person1; //将person1对象赋值给person2对象

var_dump($person1);
/*
$person1输出如下:

object(Person)#1 (2) {
  ["name"]=>
  string(9) "韩顺平"
  ["age":"Person":private]=>
  int(35)
}

*/

var_dump($person2);
/*
$person2输出如下:

object(Person)#1 (2) {
  ["name"]=>
  string(9) "韩顺平"
  ["age":"Person":private]=>
  int(35)
}

*/


//引用传值

//修改person2的属性
$person2->name = '李东超';


var_dump($person1);
/*
object(Person)#1 (2) {
  ["name"]=>
  string(9) "李东超"
  ["age":"Person":private]=>
  int(35)
}

*/


var_dump($person2);
/*
 object(Person)#1 (2) {
  ["name"]=>
  string(9) "李东超"
  ["age":"Person":private]=>
  int(35)
}

*/

/*由于修改了$person2->name = '李东超'
此时输出$person1和$person2会看到$person1和$person2的name属性都变成了李东超,由此可见对象之间传值是引用传值
*/

对象比较

//定义一个类
class Person
{
    //属性
    public $name;
    private $age;

    //构造方法
    public function __construct($name,$age)
    {
        $this->name = $name;
        $this->age  = $age;
    }
}

//实例化对象
$person1 = new Person('张三丰',108);
$person2 = new Person('谢逊',45);
$person3 = new Person('张三丰',108);
$person4 = $person2;

var_dump($person1 == $person2);       //false 因为属性值不相同
var_dump($person1 == $person3);       //true,因为两个对象的属性数量和值都相同,而且同属于一个类的对象
var_dump($person1 === $person3);   //false 因为这是属于两个不同的对象
var_dump($person2 == $person4);       //true
var_dump($person2 === $person4);   //true,取的是同一块内存地址里的内容进行比较

类常量访问

方法中不能直接访问类常量。原因:常量是属于类,只有类才能访问

类访问常量

语法: 类名::常量名字(类的外部)

类的内部访问常量除了 类名::常量名字 也可以在类的内部使用self::常量名字 self代表本类 $this代表当前对象

案例:

//类常量操作
class MyMath
{
    //属性
    public $opr = array('+','-','*','/','%');

    //定义一个类的常量PI
    const PI = 3.1425926;

    //定义一个求圆的面积的一个方法
    public function circleArea($r = 10)
    {
        //面积 = π * r^2
        //return MyMath::PI * $r * $r;  //类名::PI (这种方式也可以访问到类常量,类的外部访问常量只能使用这种方式,不能使用self::的方式)
        return self::PI * $r * $r;
        /*在类的内部访问常量推荐使用self关键字访问,self代表本类的意思,当然self只能在类的内部使用 类的外部不能使用self 因为在外部self不知道具体要找那个类。。
        好处:如果类的名字发生改变,你不需要一个一个将之前的类名修改成现在的新的类名*/
    }
}


$mymath = new MyMath(); //实例化对象

//对象访问常量
//echo $mymath->PI;    //系统处理:$PI,没有定义,所以错误

//求圆的面积
echo $mymath->circleArea();     //输出:314.25926


//类的外部访问常量
echo MyMath::PI;   //::双冒号是范围解析操作符  输出:3.1425926

self与$this的区别

1.区别: 代表不一样的内容:self代表类,$this代表对象

2.区别: 访问的内容也不一样:self访问类常量,$this访问属性和方法(普通)

3.区别: self与$this访问数据的方式不一样,self使用范围解析操作符(::),$this使用对象访问符(->)

4.相同: 都是在类中使用(都是在方法里面使用)


声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

精彩评论

全部回复12人评论7,777人参与