zoukankan      html  css  js  c++  java
  • php对象

    php.net

    对象

    在类定义内部,可以用 new self 和 new parent 创建新对象。
    当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。可以用克隆给一个已创建的对象建立一个新实例。

    <?php
    
    $instance = new SimpleClass();
    
    $assigned   =  $instance;
    $reference  =& $instance;
    
    $instance->var = '$assigned will have this value';
    
    $instance = null; // $instance and $reference become null
    
    var_dump($instance);
    var_dump($reference);
    var_dump($assigned);
    ?>
    

    输出:

    NULL
    NULL
    object(SimpleClass)#1 (1) {
       ["var"]=>
         string(30) "$assigned will have this value"
    }
    

    PHP 5.3.0 引进了两个新方法来创建一个对象的实例:

    <?php
    class Test
    {
        static public function getNew()
        {
            return new static;
        }
    }
    $obj1 = new Test();
    $obj2 = new $obj1;	//第一种
    $obj3 = Test::getNew();	
    

    自 PHP 5.5 起,使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。

    类常量

    可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号

    <?php
    class MyClass
    {
        const constant = 'constant value';
    
        function showConstant() {
            echo  self::constant . "
    ";
        }
    }
    

    静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)

    抽象类

    任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。

    <?php
    abstract class AbstractClass
    {
     // 强制要求子类定义这些方法
        abstract protected function getValue();
        abstract protected function prefixValue($prefix);
    
        // 普通方法(非抽象方法)
        public function printOut() {
            print $this->getValue() . "
    ";
        }
    }
    

    Trait

    传统继承增加了水平特性的组合,避免传统多继承和 Mixin 类相关典型问题。优先级:当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。

     <?php
    trait ezcReflectionReturnInfo {
        function getReturnType() { /*1*/ }
        function getReturnDescription() { /*2*/ }
    }
    
    class ezcReflectionMethod extends ReflectionMethod {
        use ezcReflectionReturnInfo;
        /* ... */
    }
    
    class ezcReflectionFunction extends ReflectionFunction {
        use ezcReflectionReturnInfo;
        /* ... */
    }
    

    多个 trait

    通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World';
        }
    }
    
    class MyHelloWorld {
        use Hello, World;
        public function sayExclamationMark() {
            echo '!';
        }
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    

    解决trait冲突

    如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
    需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。as 操作符可以将其中一个冲突的方法以另一个名称来引入。
    示例:定义了使用 trait B 中的 smallTalk 以及 trait A 中的 bigTalk,用了 as 操作符来定义了 talk 来作为 B 的 bigTalk 的别名。

    <?php
    trait A {
        public function smallTalk() {
            echo 'a';
        }
        public function bigTalk() {
            echo 'A';
        }
    }
    
    trait B {
        public function smallTalk() {
            echo 'b';
        }
        public function bigTalk() {
            echo 'B';
        }
    }
    
    class Aliased_Talker {
        use A, B {
            B::smallTalk insteadof A;
            A::bigTalk insteadof B;
            B::bigTalk as talk;
        }
    }
    

    修改访问控制权限

    使用as

    <?php
    trait HelloWorld {
        public function sayHello() {
            echo 'Hello World!';
        }
    }
    
    // 修改 sayHello 的访问控制
    class MyClass1 {
        use HelloWorld { sayHello as protected; }
    }
    
    // 给方法一个改变了访问控制的别名
    // 原版 sayHello 的访问控制则没有发生变化
    class MyClass2 {
        use HelloWorld { sayHello as private myPrivateHello; }
    }
    ?>
    

    其他

    其它 trait 也能够使用 trait。
    trait 支持抽象方法的使用。
    Trait 同样可以定义属性。

    匿名类

    匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来:

    <?php
    
    class Outer
    {
        private $prop = 1;
        protected $prop2 = 2;
    
        protected function func1()
        {
            return 3;
        }
    
        public function func2()
        {
            return new class($this->prop) extends Outer {
                private $prop3;
    
                public function __construct($prop)
                {
                    $this->prop3 = $prop;
                }
    
                public function func3()
                {
                    return $this->prop2 + $this->prop3 + $this->func1();
                }
            };
        }
    }
    
    echo (new Outer)->func2()->func3();
    

    魔术方法

    不可访问属性、不可访问方法:未定义或不可见的类属性或方法
    在给不可访问属性赋值时,__set() 会被调用。
    读取不可访问属性的值时,__get() 会被调用。
    当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
    当对不可访问属性调用 unset() 时,__unset() 会被调用。
    在对象中调用一个不可访问方法时,__call() 会被调用。
    在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
    serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。
    unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

    public void __set ( string $name , mixed $value )
    public mixed __get ( string $name )
    public bool __isset ( string $name )
    public void __unset ( string $name )
    public mixed __call ( string $name , array $arguments )
    public static mixed __callStatic ( string $name , array $arguments )
    __construct(), __destruct(), __sleep(), __wakeup(), __toString(), __invoke(),__set_state(), __clone() , __debugInfo() 
    

    示例:

    <?php
    class PropertyTest {
         /**  被重载的数据保存在此  */
        private $data = array();
    
     
         /**  重载不能被用在已经定义的属性  */
        public $declared = 1;
    
         /**  只有从类外部访问这个属性时,重载才会发生 */
        private $hidden = 2;
    
        public function __set($name, $value) 
        {
            echo "Setting '$name' to '$value'
    ";
            $this->data[$name] = $value;
        }
    
        public function __get($name) 
        {
            echo "Getting '$name'
    ";
            if (array_key_exists($name, $this->data)) {
                return $this->data[$name];
            }
    
            $trace = debug_backtrace();
            trigger_error(
                'Undefined property via __get(): ' . $name .
                ' in ' . $trace[0]['file'] .
                ' on line ' . $trace[0]['line'],
                E_USER_NOTICE);
            return null;
        }
    
        /**  PHP 5.1.0之后版本 */
        public function __isset($name) 
        {
            echo "Is '$name' set?
    ";
            return isset($this->data[$name]);
        }
    
        /**  PHP 5.1.0之后版本 */
        public function __unset($name) 
        {
            echo "Unsetting '$name'
    ";
            unset($this->data[$name]);
        }
    
        /**  非魔术方法  */
        public function getHidden() 
        {
            return $this->hidden;
        }
    }
    

    call示例:arguments是一个数组

    <?php
    class MethodTest 
    {
        public function __call($name, $arguments) 
        {
            // 注意: $name 的值区分大小写
            var_dump($arguments);
        }
    
        /**  PHP 5.3.0之后版本  */
        public static function __callStatic($name, $arguments) 
        {
            // 注意: $name 的值区分大小写
            var_dump($arguments);
        }
    }
    
    $obj = new MethodTest;
    $obj->runTest('in object context','fyfy');
    
    MethodTest::runTest('in static context');  // PHP 5.3.0之后版本
    ?>
    
    //输出类似
    /*
    array(2) {
      [0] =>
      string(17) "in object context"
      [1] =>
      string(4) "fyfy"
    }
    array(1) {
      [0] =>
      string(17) "in static context"
    }
    
    */
    

    遍历对象

    默认情况下,所有可见属性都将被用于遍历。

    <?php
    class MyClass
    {
        public $var1 = 'value 1';
        public $var2 = 'value 2';
        public $var3 = 'value 3';
    
        protected $protected = 'protected var';
        private   $private   = 'private var';
    
        function iterateVisible() {
           echo "MyClass::iterateVisible:
    ";
           foreach($this as $key => $value) {
               print "$key => $value
    ";
           }
        }
    }
    
    $class = new MyClass();
    
    foreach($class as $key => $value) {
        print "$key => $value
    ";
    }
    echo "
    ";
    
    $class->iterateVisible();
    ?>
    

    对象复制

    clone 关键字,浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。
    示例:关于浅复制

    <?php
    class subclass{
      public $var1='subclass default';
    }
    
    class MyClass
    {
        public $var1 = 'myclass default';
        public $object;
    
        function __construct(){
          $this->object=new subclass();
        }
    }
    
    $object1 = new MyClass();
    $object2 = clone $object1;
    $object1->object->var1='object1 change';
    $object1->var1='object1 change';
    
    print_r($object1);
    print_r($object2);
    ?>
    

    输出结果:

    MyClass Object
    (
        [var1] => object1 change
        [object] => subclass Object
            (
                [var1] => object1 change
            )
    
    )
    MyClass Object
    (
        [var1] => myclass default
        [object] => subclass Object
            (
                [var1] => object1 change
            )
    

    对象比较

    ==:两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。
    ===:必须是同一个对象。

  • 相关阅读:
    MongoDB 副本集搭建 & 副本集扩容
    MongoDB 部署 & 基础命令
    MyBatis常见面试题:#{}和${}的区别是什么?
    MyBatis常见面试题:说说MyBatis的工作原理
    Java四种引用类型回收时机介绍
    Java虚拟机之垃圾回收器
    Servlet中过滤器、监听器和拦截器的区别
    Java里一个线程两次调用start()方法会出现什么情况
    二叉树、二叉查找树、平衡树和红黑树概念及其性质
    转:基于Redis实现延时队列
  • 原文地址:https://www.cnblogs.com/jcuan/p/6012693.html
Copyright © 2011-2022 走看看