博客列表 >匿名类、抽象类、trait、接口、类的自动加载及对象的序列化与反序列化学习—2018年9月5日22时00分

匿名类、抽象类、trait、接口、类的自动加载及对象的序列化与反序列化学习—2018年9月5日22时00分

小星的博客
小星的博客原创
2018年09月24日 23:46:04636浏览

此次学到的东西有点多,涉及的知识有点多。

一、匿名类(即没有名称的类)

    重要知识点:匿名类  php 7.0+ 才支持,所以在使用时如果报错先查看是否是PHP版本问题。

  1. 匿名类中可以使用构造方法。

    代码:

    实例

    //1.匿名类中可以使用构造方法
    echo (new class('同学一'){
        private $name ;
    
        public function __construct($name)
        {
            $this->name = $name;
        }
        public function output($name)
        {
            return $this->name.'正在学习'.$name;
        }
    
    })->output('php');

    运行实例 »

    点击 "运行实例" 按钮查看在线实例

  2. 在匿名类中可以继承其它类中的成员

    代码:

    实例

    //2.匿名类可以继承其他类的成员
    class Student
    {
        private $time;
        public function __construct($time)
        {
            $this->time = $time;
        }
        public function __get($time)
        {
            return $this->$time ;
        }
    }
    echo (new class('zmx','Monday') extends Student{
        private $name;
        public function __construct($name,$time)
        {
            parent::__construct($time);
            $this->name = $name;
        }
        public function study()
        {
            return $this->name.'在'.$this->time.'时间上课';
    }
    })->study('同学二');

    运行实例 »

    点击 "运行实例" 按钮查看在线实例

  3. 可以在类声明中嵌套一个匿名类

    代码:

  4. 实例

    <?php
    class Pig
    {
        private $name;
        public function __construct($name)
        {
            $this->name = $name;
        }
    
        public function demo1()
        {
            // 宿主类中的私有成员不能在匿名类中直接使用
            // 可以通过在匿名类创建一个构造方法将宿主类中的私有成员进行注入
            //这里的$this->name 是父类(Pig)的成员,这里可以作为参数传入,从而达到访问父类中$name的目的
            return (new class($this->name) extends Pig{//这里也只能继承Pig类,不能继承外面的类
                public  $name;
                //这里用于接受父类中的私有成员的值。
                public function __construct($name)
                {
                    parent::__construct($name);
                    $this->name = $name;
            }
    
                public function show()
                {
    
                    echo $this->name;
                }
    
            });
        }
    }
    
    echo (new Pig('Pig'))->demo1()->show();

    运行实例 »

    点击 "运行实例" 按钮查看在线实例

二、trait的使用

    代码:

实例

<?php
/**
 * php只能实现单继承,trait打破了限制
 * 代码复用机制(函数,类的继承)
 * 使用类的语法,但不是类,所以不能实例化
 * 相当于方法集
 */
if(!class_exists('Person'))//先判断一下是否存在类
{
    class Person
    {
        protected $name;
        public function __construct($name = '小明')
        {
            $this->name = $name;
        }
        public function study($course  = 'php')
        {
            return $this->name.'在学习'.$course;
        }
    }
}
trait Course
{
    public $friend = '小华';
    public function sport($sport = '踢足球')
    {
        return $this->name.'在学习'.$sport;
    }
    public function study($course  = '篮球')
    {
        return $this->friend.'在学习'.$course;
    }
}
trait Sport
{
    public $friend = '小华';
    public function sport($sport = '排球')
    {
        return $this->name.'在学习'.$sport;
    }
    public function study($course  = '排球')
    {
        return $this->friend.'在学习'.$course;
    }
}

//父类与trait类的关系:trait类位于父类与子类之间,覆盖了父类

class Student extends Person
{
//    use Course;//导入一个trait类
//    use Sport;

    use Course,Sport{
        Course::sport insteadof Sport;//用Course中的sport方法代替Sport中的sport
        Sport::sport as Ssport;//更名
        Sport::study insteadof Course;//用Sport中的study方法代替Course中的study
        Course::study as Cstudy;//更名
    }

}

$student = new Student();
echo $student->sport();
echo $student->Ssport();

运行实例 »

点击 "运行实例" 按钮查看在线实例

三、抽象类(abstract)

    重要知识点:抽象类必须被继承才可以使用,抽象类不可以实例化。

                        抽象类中声明的抽象方法必须在它的继承类实现。

    代码:

实例

<?php
/**
 * 抽象类
 * 抽象类必须被继承才可以使用,抽象类不可以实例化
 * 抽象类中尽可能不要出现静态方法,会比较麻烦
 */
header('Content-type:text/html;charset=utf-8');
abstract class Fruit
{
    private $name ;

    public function __construct($name)
    {
        $this->name = $name;
    }

    //这里声明的抽象方法必须在它的继承类实现,否则会报错
    abstract public function eat();//声明抽象方法后,不能有执行的代码,同时,该类会变成抽象类,所以类前也应该加上abstract
//    {
//        return $this->name.'能吃';
//    }
}

//echo (new Fruit('apple'))->eat();//声明成抽象类后就不能再实例化了

class Apple extends Fruit
{
    private $name;
    public function __construct($name1,$name2)
    {
        parent::__construct($name2);
        $this->name = $name1;
    }
    public function eat()//父类中有eat()这个抽象方法,这里必须要实现
    {
        return $this->name.'比较大';
    }
    public function eats()
    {
        return $this->name.'比较大';
    }
}
echo (new Apple('西瓜','草莓'))->eats();

//怎么感觉抽象类没什么用

运行实例 »

点击 "运行实例" 按钮查看在线实例

四、接口(interface)

代码:

实例

<?php
/**
 * 接口
 * 接口方法必须是public
 * 接口中可以使用常量,不过必须初始化
 * 接口中方法只声明不实现
 * 必须要实现接口中的方法,连参数都不能少
 */
header('Content-type:text/html;charset=utf-8');

interface Animals
{
    const CAT = '猫';
    //接口中方法只声明不实现
    public function eat($food);

}
interface Feature
{
    public function good($good);

}
class Cat implements Animals
{
    private $name = '橘猫';
    //必须要实现接口中的方法,连参数都不能少
    public function eat($food)
    {
        return $this->name.'吃'.$food;

    }
}
class Dog implements Animals,Feature//可以继承多个接口
{
    private $name = '二哈';
    //必须要实现接口中的方法,连参数都不能少
    public function eat($food)
    {
        echo $this->name.'吃'.$food.'<br>';
        //这里为了能够链式调用,所以返回$this
        return $this;
    }

    public function good($good)
    {

        return $this->name.'的优点是:'.$good.'<br>';
    }
}
echo (new Cat())->eat('猫粮');

echo (new Dog())->eat('肉')->good('傻');


interface Phone
{
    public function test($a);
}
class A implements Phone,Animals
{
    public function eat($food){

    }
    public function test($a){

    }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

 五、类的自动加载

代码:

实例

<?php
/**
 * 类的自动加载
 */
//spl_autoload_register(function($classname){
//    $classname = str_replace("\\","/",$classname);
//    require './class/'.$classname.'.php';
//});

//另一种写法
function auto($classname)
{
    require './class/'.$classname.'.php';
}
spl_autoload_register('auto');//注意啊,是s p l,不是sql,  是P,错了好几次了
echo Demo1::CLASS_NAME;//这里会自动触发spl_autoload_register(),自动导入相应的类

运行实例 »

点击 "运行实例" 按钮查看在线实例

七、克隆

两点:1.  在对象复制时,在class中需要声明 __clone() 方法。

          2.  对象复制时,$a = clone $b; clone关键字别忘了加。

八、对象序列化与反序列化

重要知识点:对象序列化只保存对象中的属性,不保存方法,只保存类名,不保存对象名。

代码:

实例

<?php
/**
 * 对象的序列化
 */
//$num = 500;
//echo serialize($num),'<hr>'; // i:500;
//$name = 'peter';
//echo serialize($name), '<hr>'; // s:5:"peter";
//$course = ['a','b',4];
//echo serialize($course), '<hr>';

class Db
{
    //连接参数与返回值
    public $db = null;
    public $host;
    public $user;
    public $pass;
    
    public function __construct($host='127.0.0.1', $user='root', $pass='root')
    {
        $this->host = $host;
        $this->user =  $user;
        $this->pass = $pass;
        // 确保实例化对象的时候能自动连接上数据库
        $this->connect();
    }

    //数据库连接
    private function connect()
    {
        $this->db=mysqli_connect($this->host,$this->user,$this->pass);
    }

    //对象序列化的时候自动调用
    public function __sleep()
    {
        return ['host','user','pass'];
    }

    //执行反序列化时触发
    public function __wakeup()
    {
        $this->connect();
    }

}

$obj = new Db();
/**
 * 对象序列化的特点:
 * 1. 只保存对象中的属性,不保存方法
 * 2. 只保存类名,不保存对象名
 */

echo serialize($obj),'<hr>';
$tmp = serialize($obj);
var_dump(unserialize($tmp));

运行实例 »

点击 "运行实例" 按钮查看在线实例

面向对象学习总结:

面向对象主要是就是围绕类与对象展开,首先学习到的是面向对象的三大特征:封装、继承、多态,在学完之后,个人感觉封装的概念较为重要,对成员的访问进行限制,属性重载才能发挥作用,继而体现出封装的思想。类与对象的关系:类是对象的模板,对象是类的一个实例,差不多相当于分类的意思。类中只有属性与方法,类内部对成员进行封装,类与类之间可以进行继承,子类可以调用父类成员,也可以覆盖父类成员,父子关系可以让类变的很灵活,体现了多态性。

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议