• 1. 星际争霸之php面向对象(一)


    题记
    ==============================================================================
    本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦!

    本文地址:http://www.cnblogs.com/davidhhuan/p/4248062.html
    ==============================================================================


    前言

    面向对象博大精深,对于从未接触过得的人,会觉得一头雾水。
    学习的资料很多,但大多比较抽象,所以我用经典的游戏-星际争霸来讨论PHP面向对象。
    现在假设我们来用PHP开发星际争霸,从而接触PHP面向对象。
    注意,为了便于学习,除了特殊说明,否则各部分代码之间没有关联。而且同一件事情往往用的是不同的代码。
    另外我也不去考证各个兵种的属性数字,仅仅用来说明。


    一、类和对象

    如果玩家制造了一个机枪兵,那么我们怎么表示他呢,因为每个机枪兵有几个基本的数据要记录:剩余的血,杀敌数量,攻击力等等。
    我们可以用一个数组来记录一个机枪兵剩余的血和杀敌数量,因为这对于每个机枪兵是独立的。
    但攻击力比较麻烦,因为经过升级,攻击力会增加,这就必须要找出所有表示机枪兵的数组,然后进行修改,非常麻烦。
    从这里我们可以看出一件事情,首先每个机枪兵有独立的数据需要记录和修改,比如剩余的血。同时他们有相同的数据需要共用,比如攻击力。
    这时候面向对象就能帮上我们的忙了。

    1.1、类的定义

    我们先来处理一部分问题,也就是每个机枪兵独有的数据。

    <?php 
        class marine
        {
            public $blood = 50; //剩余的血
            public $kills = 0; //杀敌数量
    
            //这个函数(通常叫做方法)表示攻击敌人时候的运行代码
            function attack($enemy)
            {
                //攻击敌人的代码
            }
        }
    ?>

    这叫做类,我们建立了一个表示所有机枪兵的类marine,这里面保留了需要每个兵独有的数据,比如上面代码里的剩余的血。

    1.2、对象的创建和使用

    接下来我们来使用对象,也就是每个机枪兵:

    <?php
        $m1 = new marine();
    ?>

    通过new后面加一个类的名字和括号,我们新建了一个机枪兵$m1,$m1被叫做类marine的对象,我们可以把它想象成一个特殊变量,只不过里面保存了多个数据。
    如果需要使用或者操作某个机枪兵的血(对象的属性),只要用$m1->blood来表示就可以了:echo $m1->blood;//输出机枪兵$m1剩余的血
    我们再建立一个机枪兵

    <?php 
        $m2 = new marine();
    ?>

    如果此时$m1被敌人攻击过了,还剩下10个血。而$m2没受过攻击:

    <?php
        echo $m1->blood;//结果是10
        echo $m2->blood;//结果是50
    ?>

    使用对象可以很简单的保存每个机枪兵的血,不会互相影响。
    如果机枪兵$m1攻击敌人的时候,可以这样使用对象的方法:

    <?php
        $m1->attack($z1);//假设攻击的是某个小狗的对象$z1
    ?>

    不同的类内可以用同名的函数,比如小狗的类Zergling里面也可以有一个函数attack
    要注意的是,从PHP5开始,无论在哪里改变一个对象的属性,都能改变它。比如上面一个小狗对象被作为参数传入机枪兵的attack函数,执行函数之后这个小狗对象的血减少了,这和一般的函数不同。但这是很直观的,如果一个小狗被攻击了,它的血就应该减少。

    二、构造函数和析构函数

    每次我们新建一个机枪兵的时候,总人口应该加1,如果一个机枪兵被杀,人口应该减少1。
    可以通过构造函数和析构函数来自动处理:

    <?php
        class marine
        {
            //构造函数
            function __construct()
            {
                //增加总人口的代码
            }
    
            //析构函数
            function __destruct()
            {
                //减少总人口的代码
            }
        }
    ?>

    在一个类中,名字为__construct的函数叫做构造函数,每次new新建一个类的对象的时候就会执行:

    <?php
        $m1 = new marine();//每次制造一个机枪兵时系统会调用类marine的构造函数,自动增加总人口
    ?>

    在一个类中,名字为__destruct的函数叫做析构函数,每次销毁一个类的对象的时候就会执行:

    <?php
        unset($m1);//unset可以用于对象,表示销毁一个对象。每次一个机枪兵被杀时系统会调用类marine的析构函数,自动减少总人口
    ?>

    三、静态

    机枪兵的攻击力是属于所有机枪兵对象,每个机枪兵的攻击力都是一样的,如果升级,应该一起变化。
    这就用到static,表示静态:

    <?php
        class marine
        {
            static $attackNumber = 10; //攻击力的数字
    
            //这个函数表示攻击敌人时候的运行代码
            function attack($enemy)
            {
                //攻击敌人的代码,$enemy->blood表示敌人对象的血属性
                $enemy->blood -= self::$attackNumber;
            }
        }
    ?>

    静态属性表示类所有的对象都共享的属性,一旦改变,所有的对象都跟着变化。
    静态属性用static开头,比如上面的static $attackNumber。
    静态属性可以用类直接访问:

    <?php
        echo marine::$attackNumber;//显示10
    ?>

    如果类以内的函数访问,用self::$attackNumber表示本类的$attackNumber属性
    所以如果我们升级了机枪兵的攻击力,所有的机枪兵都受影响,这就是面向对象的好处之一,也解决了我们前面讨论的共同数据的问题。

    函数也可以是静态的,这样就可以用类直接访问,不需要新建对象来调用:

    <?php 
        class marine
        {
            static $attackNumber = 10; //攻击力的数字
    
            //这个函数表示机枪兵升级的运行代码
            staticfunction upgrade()
            {
                self::$attacknum++;
            }
        }
    ?>

    如果科技建筑升级完毕,直接就调用这个函数:

    <?php
        marine::upgrade();
    ?>

    四、继承

    兵营用来造机枪兵,坦克房用来制造坦克,他们都是建筑,但是却有很多不同,如果用一个类“建筑”来表示,很困难。
    但我们要保留他们的共性,比如都能飞行,不希望飞行的代码在各个类重复写,又要让他们能各自独立的生产不同的东西。
    所以我们可以用继承来处理,继承表示父子关系,被继承的叫父类,继承的叫子类。用extends表示继承

    <?php 
        //建筑类
        class building
        {
            function fly()
            {
                //建筑飞行的代码
            }
        }
    
        //兵营类
        class marineBuilding extends building
        {
            function createMarine()
            {
                //制造机枪兵的代码
            }
        }
    
        //坦克房类
        class tankBuilding extends building
        {
            function createTank()
            {
                //制造坦克的代码
            }
        }
    ?>

    接下来,我们看看继承产生的效果:

    <?php 
        //如果造了一个兵营:
        $mb1 = new marineBuilding();
    
        //一旦他需要飞行,就可以直接使用建筑类的函数fly(),尽管兵营类的定义里没有这个函数
        $mb1->fly();
    
        //而他要制造机枪兵的时候:
        $mb1->createMarine();
    ?>

    同样是继承建筑类的坦克房类,就无法制造机枪兵,因为这是兵营类的个性。
    如果在子类中的函数调用父类的函数,要使用parent,比如parent::fly()
    注意,一个类只能有一个父类,PHP不允许多重继承,也就是说一个孩子只能有一个爹,一个爹可以有N个孩子!

    相关文章:

    1. 星际争霸之php面向对象(一)

    2. 星际争霸之php面向对象(二)

    3. 星际争霸之php设计模式--简单工厂模式

    4. 星际争霸之php设计模式--工厂方法模式

    5. 星际争霸之php设计模式--抽象工厂模式

    6. 星际争霸之php设计模式--建造器模式

    7. 星际争霸之php设计模式--中介者模式

    8. 星际争霸之php设计模式--享元模式

    9. 星际争霸之php设计模式--代理模式

    10. 星际争霸之php设计模式--原型模式

    11. 星际争霸之php设计模式--备忘模式

    12. 星际争霸之php设计模式--模板模式

    13. 星际争霸之php设计模式--正面模式

    14. 星际争霸之php设计模式--状态模式

    15. 星际争霸之php设计模式--策略模式

    16. 星际争霸之php设计模式--组合模式

    17. 星际争霸之php设计模式--职责链模式

    18. 星际争霸之php设计模式--观察者模式

    19. 星际争霸之php设计模式--迭代器模式

    20. 星际争霸之php设计模式--适配器模式

  • 相关阅读:
    js获取前一页面连接的参数值
    window.onload()函数和jQuery中的document.ready()有什么区别
    jquery中$.get()提交和$.post()提交有区别吗?
    JQuery有几种选择器?
    jQuery 库中的 $() 是什么?
    JavaScript内置可用类型
    .JS 中 == 和 === 区别是什么
    undefined,null 和 undeclared 有什么区别
    JS中如何将页面重定向到另一个页面
    数据库设计中,一对多如何处理?
  • 原文地址:https://www.cnblogs.com/davidhhuan/p/4248062.html
Copyright © 2020-2023  润新知