zoukankan      html  css  js  c++  java
  • php-面向对象

    • 函数

      // 匿名函数也叫做闭包函数,允许临时创建一个没有指定名称的函数,最经常用作回调函数参数的值。
      
      
    • 类与对象

      // 1.类的定义
      class SimpleClass
      {
          // 声明属性
          public $var = 'a default value';
          // 声明方法 
          public function displayVar() {
              echo $this -> var
          }
      }
      
      /*
      $this说明
      假如类的对象去调用类里定义的方法,那么这个$this就是这个对象,如果是类去使用的话,那么这个$this是没有值的。
      
      关于$this,在php5和php7中有部分是不一样的
      
      假如有两个对象(a,b),这两个对象对应的类是不一样的,一个对象(a)里的方法调用了另一个类(b对象的类)里的方法,那个类里的方法有一个$this这个属性,那么此时这个$this的值应该是什么呢?
      
      1.在php5中,这个$this就是a这个对象
      2.在php7中,这个$this是没有值的
      */
      
      // 对象的创建,也就是类的实例
      $zhuyu = new People();
      // 也可以这样
      $className = 'People';
      $zhuyu = new $classNanme();
      
      // 对象赋值
      $zhuyu = new $People();
      $zhuchunyu = $zhuyu;
      $zhu = &$zhuyu;
      
      $zhuyu -> var = 'var';
      $zhuyu = null;
      
      var_dump($zhuyu);      // 输出值为null
      var_dump($zhu);		   // 输出值为null
      var_dump($zhuchunyu);   // 有输出值
      
      /*
      简化上面的结论,大概就是这样一段代码
      $b = $a;
      $c = &$a;
      $a = null;
      首先$b = $a;这行代码就是一个普通的赋值,那么$b所对应的$a所对应的值的内存地址,它和$a是是没有丝毫关系的
      再看$c = &$a;这是引用赋值吧,所以说$c对应的值的内存地址和$a所对应的值的内存地址是息息相关的,它是跟着$a所变换的
      最后$a = null;这也是一个普通的赋值,那么$a对应的是null的内存地址,之前$c的值是个$a的值是有关系的,所以$c也变成了null,$b的内存地址还是对应之前的内存地址。
      */
      
      // 创建新对象
      class Test
      {
          static public function getNew()
          {
              return new static;
          }
      }
      class Child extends Test{}
      
      $obj1 = new Test();
      $obj2 = new $obj1;
      var_dump($obj1 !== $obj2);     // ture
      
      $obj3 = Test::getNew();
      var_dump($obj3 instanceof Test);
      
      $obj4 = Child::getNew();
      var_dump($obj4 instanceof Child);
      
      /*
      方式一:通过new一个类去创建一个对象
      方式二:通过调用类里的方法,创建一个新对象
      */
      
      /*
      对象属性
      属性声明是由关键字开头:public protected private
      访问非静态属性方式:->
      访问静态属性方式:::
      */
      
      // 类常量
      class A 
      {
          const constant = 'constant value';
      }
      
      // 构造方法 __construct()  相当于python中的__init__()
      class People extends BaseClass
      {
          function __construct() {
              // 实力对象之前,先执行偶
              print '创建一个实例,先执行__construct';
              $this -> name = '朱春宇'
              // 调用父类的__construct(),
              parent::__construct();
          }
      }
      
      // 析构函数 __destruct 相对于python中 __del__方法
      // 在删除一个对象之前,会先执行__destruct方法
      class Test
      {
          function __destruct(){
              print 'del'.$this -> name . '
      '
          }
      }
      
      // 访问控制(可见性)
      /*
      对属性或者方法的访问控制,是通过在前面添加关键字public(公有),
      protected(受保护),pricate(私有)来实现的
      public:可以在任何地方都可以被访问
      protected:可以被自身及其子类和父类访问
      private:只能被它所在的类才能访问
      private相当于python中封装的思想,只能在类内部使用。
      */
      
      // 对象继承  extends
      /*
      子类继承父类,会继承父类所有的共有方法,受保护的方法,子类也可以重写父类的方法。
      */
      
      // 范围解析操作符(::)
      /*
      可以用来访问静态成员,类常量,还可以用于覆盖类的属性的方法和属性
      比如调用父类的方法 parent::__construct
      */
      
      // 静态关键字(static)
      /*
      声明类的属性或方法为静态,就可以不实例化类而直接访问,静态属性是不能通过类实例的对象去访问的,而静态方法是可以的
      访问静态属性和方法的方法都是::
      */
      
      // 抽象类实例
      abstract class Test
      {
          // 强制要求子类定义这些方法
          abstract public function getValue();
          abstract public function prefixValue();
          
          // 非抽象方法
          public function foo(){
              print '非抽象方法foo';
          } 
      }
      
      class Test1 extends Test
      {
          public function getValue()
          {
              // getvalue方法代码
          }
          public function prefixValue(){
              // prxfixValue方法代码
          }
      }
      /*
      对于抽象类的理解:
      1.和python中abc库差不多,控制子类的一些方法属性,必须有。
      2.达到上面抽象类的效果,也可以通过主动抛异常去实现,在父类定义一个函数,直接抛异常,如果继承他的类没有重写该方法,在使用到这个方法的时候,便会执行父类的方法,直接抛异常。
      */
      
      // 对象接口
      /*
      可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容
      
      接口是通过interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的
      
      接口中定义的所有方法都必须是公有,这就是接口的特性
      */
      
      // 声明一个'iTemplate'接口
      interface iTemplate
      {
          public function setVariable($name,$var);
          public function getHtml($template);
      }
      
      // 实现接口
      class Template implements iTemplate
      {
          private $vars = array();
          public function setVariable($name,$var)
          {
              $this -> vars[$name]=$var;
          }
          public function getHtml($template)
          {
              foreach($this->vars as $name=>$var){
                  $template = str_replace('{'.$name.'}',$value,$template);
              }
              return $template;
          }
      }
      
      // 接口之间的继承,
      interface a
      {
          public function faa();
      }
      
      interface b extends a
      {
          public function fbb();
      }
      
      class c implements b
      {
          // 这个c如果想要实现a,b接口,那么必须要有a,b接口里的所有方法
          public function faa();
          public function fbb();
      }
      
      
      /*
      抽象类与接口之间相同之处和不同之处
      1.相同点
      - 两者都是抽象类,不能进行实例化
      - interface实现类及abstract class的子类都必须实现已经声明的抽象方法
      2.不同点
      - 接口实现需要implements,抽象类实现需要继承(extends)
      - 接口中声明的方法都必须是public(公有的),而抽象类声明的方法(这个方法带有abstract),可以是public,protected,但绝不能是private。如果抽象类中的方法是public类型的话,那么继承它的类的这个方法必须是public,如果抽象类中的方法是protected类型,那么
      继承它的类的方法应该是public或者protected类型。
      - 接口中声明的方法,只能是方法名,方法里面不能有代码块。抽象类中声明的方法可以有
      - 一个类可以实现多个接口,但是只能继承一个抽象类
      */
      
      
      // trait 一种代码复用的方法
      tarit speak {
          public function speakHello(){
              print 'hello'."
      ";
          }
          $name = 'zhuyu';
      }
      
      class A
      {
          $name = 'zhuchunyu';
      }
      
      class B extends A{
          use speak;
      }
      
      b = new B();
      print b->name;
      
      // 匿名类
      /*比如一些函数需要的参数需要传递类,那么可以直接new 类名()*/
      
      // 重载:
      /*
      定义:是指动态地创建类属性和方法,我们是通过魔法方法来实现
      注意:1.所有重载方法都必须声明为public
      	 2.这些魔法方法的参数都不能通过引用传递
      	 3.php中的重载与其他绝大多数面向对象语言不同。传统的“重载”是用于提供多个同名的类方法,但各方法的参数类型和个数不同
      */
      // 属性重载
      /*
      - 在给不可访问属性赋值时,__set(%name,$value)会被调用。
      - 读取不可访问属性的值时,__get(%name)会别调用。
      - 当对不可访问属性调用isset()或empty()时,__isset()会被调用。
      - 当对不可访问属性调用unset()时,__unset()会被调用。
      */
      // 方法重载
      /*
      - __call:在对象中调用一个不可访问的方法时,被调用
      - __callStatic:在静态上下文中调用一个不可访问方法时,被调用
      */
      
      // 遍历对象 foreach
      class A
      {
          public $name = '朱宇';
          public $age = 18;
          public $sex = '男';
      
          protected $top = '1.71';
          private $a = 'aa';
      
          public function myForEach() {
              foreach ($this as $key=>$value){
                  echo $key.'='.$value."
      ";
              }
          }
      }
      
      $a = new A();
      
      foreach ($a as $item=>$value){
          echo $item.'='.$value."
      ";
      }
      
      $a->myForEach();
      
      /*
      - 外面这个foreach的输入结果是没有protected,private的值的
      - 函数内部里的foreach可以显示所有的属性的
      - foreach它只能循环它能访问的属性
      */
      
      // 魔法方法
      /*
      1.__construct(),它会在new一个对象之前触发执行
      2.__destruct(),它会在del一个对象之前,运行。
      3.__call,它会在调用一个方法,并且这个方法不存在的时候执行
      4.__callStatic,它会在调用一个静态方法,并且这个方法不存在的时候执行
      5.__get(),获取一个对象的属性,并且这个属性不存在的话,那么便会执行这个魔法方法
      6.__set(),再给对象的一个属性赋值时,并且这个属性不能访问,那么就会执行这个方法
      7.__isset,执行isset()函数的时候,先执行
      8.__unset,执行unset()函数的时候,先执行
      9.__sleep(),在执行serialize()这个函数的时候,会检查类中是否存在该魔法方法,有的话,会先调用__sleep()这个方法,然后在执行序列化操作。这个方法的返回值应该是一个数组,如果这个方法没有返回值的话,那么null则会被序列化,并且产生一个E_noteic级别的错误。
      10.__wakeup(),会在执行unserialize这个函数的,会先执行该魔法方法。
      11.__toString(),这个方法在打印一个对象的时候,自动触发,返回值必须是字符串,和python中的__str__
      12.__invoke(),当尝试以调用函数的方法调用一个对象时,__invoke()自动触发,和python中__call__
      13.__set_state(),
      14.__clone(),
      15.__debuginfo(),
      16.__autoload(),
      */
      
      // final关键字
      // 如果父类中的方法被声明为final,则子类无法覆盖该方法,如果一个类被声明为final,则不能被继承
      // final方法示例
      class BaseClass
      {
          public function faa(){
              print 'faa'."
      ";
          }
          final public function fbb(){
              print 'fbb'."
      ";
          }
      }
      
      class AClass extends BaseClass
      {
          public function fbb(){
              print 'AClass fbb'."
      ";
          }
      }
      
      $a = new AClass();
      $a->fbb();
      
      // final类实例
      final class BaseClass
      {
          public $name;
      }
      
      class AClass extends BaseClass{}
      
      $a = new AClass();
      echo $a ->name;
      
      
      // 对象复制 __clone方法
      class SubObject
      {
          static $instances = 0;
          public $instance;
      
          public function __construct() {
              $this->instance = ++self::$instances;
          }
      
          public function __clone() {
              $this->instance = ++self::$instances;
          }
      }
      
      class MyCloneable
      {
          public $object1;
          public $object2;
      
          function __clone()
          {
            
              // 强制复制一份this->object, 否则仍然指向同一个对象
              $this->object1 = clone $this->object1;
          }
      }
      
      $obj = new MyCloneable();
      
      $obj->object1 = new SubObject();
      $obj->object2 = new SubObject();
      
      $obj2 = clone $obj;
      
      
      print("Original Object:
      ");
      print_r($obj);
      
      print("Cloned Object:
      ");
      print_r($obj2);
      /*
      上面的打印的效果为   $obj -> object1为 1 ,$obj -> object2为 2
      				  $obj2 -> object1为 3 ,$obj -> object2为 2 
      首先__clone方法只有调用clone这个方法,才会去执行
      在执行$obj2 = clone $obj这行代码之前,$obj这个对象的的属性值为 object1为1,object2为2,
      在执行$obj2 = clone $obj这行代码的时候,首先会去执行$obj这个对象里的__clone方法,这个$obj是类MyCloneable的对象,那么就去看这个类里的__clone方法,这个方法执行这行代码$this->object1 = clone $this->object1;首先会执行clone $this->object1这行代码,$this->object1对应的是SubObject类的对象,便会执行该类里的__clone方法,此时$instances的值为2,那么执行__clone之后的话,$instance的值就是3了,最终的代码为 $this->object1 = 一个SubObject的对象,对象里$instance的值为3。
      */
      
      // 对象比较
      /*
      1.使用(==)双等号进行比较的话,比较的原则是:如果两个对象的属性和属性值都相等,并且两个对象是同一个实例,那么这两个对象变量相等。
      2.如果使用(===)全等符号,这两个对象变量一定要指向某个类的同一个实例(即同一个对象)
      
      思考  $a=$b它是怎么个过程,$a,$b都是一个对象
      */
      
      // 类型约束:在方法或者函数的参数之前,加一个类型,就是对参数的类型约束了。
      
      // 后期静态绑定
      /*
      用法:self::对当前类的静态引用,__CLASS__是当前对象的类名
      	 static::
      	 parent::执行器父类的方法
      */
      
      // 对象和引用
      /*
      关于这行代码 $a = $b,($b只是一个类的对象),在php的对象编程中,我觉得就是引用传递,$a,$b它们指向的内置地址都是同一个,所有一旦其中一个改变属性,对应的它对应的内存地址的值发生改变,所有另一个变量也会进行改变。
      */
      
      // 对象序列化
      /*
      php里面的值,都可以使用函数serialize()来返回一个包含字节流的字符串来表示,unseralize()函数则是能够把字符串重新转换为原来的php值。序列化一个对象会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字
      */
      
  • 相关阅读:
    [设计模式] 10 外观模式 facade
    [设计模式] 11 享元模式 Flyweight
    [设计模式] 9 装饰者模式 Decorator
    [设计模式] 8 组合模式 Composite
    float2int
    《ASP.NET》数据绑定——GridView
    Android Studio左边栏Project不见了?
    Linux下的五种I/O模型
    Shell编程入门(第二版)(下)
    Android訪问网络,使用HttpURLConnection还是HttpClient?
  • 原文地址:https://www.cnblogs.com/zhuchunyu/p/10648676.html
Copyright © 2011-2022 走看看