php面向对象


面向对象

OOP(Object oriented programming).

面向对象三大基本特征:封装,继承,多态.

面向对象设计标准:高内聚低耦合

类 // 定义了一件事件的抽象特点.类的定义包含了数据的形式以及对数据的操作.

对象 // 是类的实例.

成员变量 // 定义在类内部的变量.该变量的值对外是不可见的,但是可以通过成员函数访问, 在类被实例化为对象后,该变量即可称为对象的属性.

成员函数 // 定义在类的内部,可用于访问对象的数据.

继承 // 继承性是子类的自动共享父类数据结构的方法的机制,这是类之间的一种关系. 在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行, 把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容.

父类 // 一个类被其他类继承,可将该类称为父类,基类,超类.

子类 // 一个类继承其他类称为子类,派生类.

多态 // 多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果. 不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性.

重载 // 简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形, 这样的同名不同参的函数或者方法之间,互相称之为重载函数或者方法.

抽象性 // 抽象性是指将具有一致的数据结构和行为的对象抽象成类. 一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容. 任何类的划分都是主观的,但必须与具体的应用有关.

封装 // 封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内.

构造函数 // 主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.

析构函数 // 析构函数与构造函数相反,当对象结束其生命周期时,系统自动执行析构函数.析构函数往往用来做"清理"工作.

class myClass{
    var $x;
    var $y = 'Hello World!';
    public function fun($x, $y){
        return $x . $y;
    }
}

面向对象设计原则

面向对象设计五项原则SOLID:

  • S:单一职责,比如图片打水印的类,它不应该不负责图片上传下载功能的实现,应该新建一个类实现.
  • O:开闭原则,当类的方法不能满足需求时,对内修改关闭,对外以接口形式开放让实现类扩展功能.
  • L:替代原则,就是允许子类重写父类的方法.
  • I:接口隔离,接口只规定公用方法,差异的方法另用一个接口.
  • D:依赖倒置,控制反转的意思,提倡使用依赖注入,依赖接口而不依赖具体实现.

mvc模式的理解

m model
v view
c controller
请求访问controller,对过controller进行逻辑处理,
基需要进行数据增删改查,则通过controller处理好数据然后调用model,
再根据model返回的数据进行处理,显示在view上。

命名空间

PHP命名空间可以解决以下两类问题:

  • 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突.
  • 为很长的标识符名称创建一个别名,提高源代码的可读性.

默认情况下,所有常量,类和函数名都放在全局空间下,就和PHP支持的命名空间之前一样.

namespace MyProject;

强制模式实例

function sum(int ...$ints){
    return array_sum($ints);
}

echo sum(2, '3', 4.1);
declare(strict_types=1);

function sum(int ...$ints){
    return array_sum($ints);
}
// PHP Fatal error
echo sum(2, '3', 4.1);

RESTful

REST(Representatioinal State Transfer), 指的是一组架构约束条件和原则

符合REST设计风格的Web API称为RESTful API

它从以下三个方面资源进行定义

  • 直观简短的资源地址:URI
  • 传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSON,XML,YAM
  • 对资源的操作:Web服务在该资源上所支持的一系列请求方法(如:POST, GET, PUT, DELETE)

class A{
    protected $name;
    public function getName(){
        return $this->name;
    }
    public function setName($name){
        $this->name = $name;
    }
}
class B extends A{
    public function getName(){
        return $this->name . '_B';
    }
    public function setName($name, $fullName = ''){
        !empty($fullName) && $name = $fullName;
        parent::setName('B_' . $name);
    }
}
$b = new B();
$b->setName('Moments');
echo $b->getName();

new

实例化一个对象

$b = new B();
$b = new B;

extends

继承关键字

class B extends A{}

::class

用于类名的解析。

namespace NS{
    class ClassName{
        public function __construct()
        {
            echo __CLASS__;
        }
    }
    echo ClassName::class;
    $tmp = new ClassName();
}
// 输出
NS\ClassName

基本概念

每个类的定义都是关键class开头。

<?php
namespace NS
{
    class A
    {
        // 成员属性
        public $temp = '成员属性';

        // 方法
        public function displayVar()
        {
            // 使用伪变量$this调用成员属性
            echo $this->temp . "<br>";
        }
    }
    // 使用new关键字实例化一个类
    $temp = new A();
    echo $temp->displayVar();

    class B extends A
    {
        // 构造方法
        function __construct()
        {
            $this->temp = '成员属性B继承于A';
        }
    }
    $temp = new B();
    echo $temp->displayVar();

    echo A::class;
}
?>

访问控制(修饰符)

对属性或方法的访问控制,是通过在前面添加关键字public(公有)、protected(受保护)或private(私有)来实现的。 公有的可以在任何地方被访问。 受保护的可以在类和子类中访问。 私有的只能被其定义所在的类访问。

成员变量使用

可以用 ->(对象运算符):$this->property(其中 property 是该属性名)这种方式来访问非静态属性。 静态属性则是用 ::(双冒号):self::$property 来访问。

类常量

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

$classname = "MyClass";
echo $classname::constant . "\n"; // 自 5.3.0 起

$class = new MyClass();
$class->showConstant();

echo $class::constant."\n"; // 自 PHP 5.3.0 起
?>

类的自动加载

spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类。

<?php
spl_autoload_register(function ($class_name) {
    require_once $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>

构造函数

<?php
class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor\n";
   }
}

class OtherSubClass extends BaseClass {
    // inherits BaseClass's constructor
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>

析构函数

<?php
class MyDestructableClass {
   function __construct() {
       print "In constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
?>

范围解析操作符(::)

范围解析操作符(也可称作Paamayim Nekudotayim)或者更简单地说是一对冒号,可以用于访问静态成员, 类常量,还可以用于覆盖类中的属性和方法。

Static(静态)关键字

由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。

静态属性不可以由对象通过 -> 操作符来访问。

用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。

抽象类

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

被定义为抽象的方法只是声明了其调用的方式(参数),不能定义其具体的功能实现。

<?php
abstract class AbstractClass
{
 // 强制要求子类定义这些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>

对象接口

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

接口是通过interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口定义的所有方法都必须是公有的,这是接口的特性。

常量

接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子类接口所覆盖。

实现(implements)

要实现一个接口,使用implements操作符。 类中必须实现接口中定义的所有方法,否则会报一个致命错误。

类可以实现多个接口,用逗号来分隔多个接口的名称。

实现多个接口时,接口中的方法不能有重名。

接口也可以继承,通过使用extends操作符。

类要实现接口,必须使用和接口中所定义的方法完全一致的方法。否则会导致致命错误。

Trait代码复用

Trait是为类似PHP的单继承语言而准备的一种代码复用机制。 Trait为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用method。 Trait和Class组合的语义定义了一种减少复杂性的方式,避免传统多继承和Mixin类相关典型的问题。

Trait和Class相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过trait自身来实例化。 它为传统继承增加了水平特性的组合;也就是说,应用的几个Class之间不需要继承。

<?php

class A
{
    public function sayHello()
    {
        echo "Hello ";
    }
}

trait mytrait
{
    public function traitFunction()
    {
        parent::sayHello();
        echo "world!";
    }

}

class B extends A
{
    use mytrait;
}

$temp = new B();
$temp->traitFunction();

优先级

当前类的方法会覆盖trait方法,而trait方法又覆盖了基类中的方法。

匿名类

PHP 7 开始支持匿名类。

<?php

// PHP 7 之前的代码
class Logger
{
    public function log($msg)
    {
        echo $msg;
    }
}

$util->setLogger(new Logger());

// 使用了 PHP 7+ 后的代码
$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});

魔术方法

public void __set ( string $name , mixed $value )

public mixed __get ( string $name )

public bool __isset ( string $name )

public void __unset ( string $name )

在给不可访问属性赋值时,__set() 会被调用。

读取不可访问属性的值时,__get() 会被调用。

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

当对不可访问属性调用 unset() 时,__unset() 会被调用。

参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了 $name 变量的值。

属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。 所以这些方法都不能被 声明为 static。从 PHP 5.3.0 起, 将这些魔术方法定义为 static 会产生一个警告。

遍历对象

PHP 5 提供了一种定义对象的方法使其可以通过单元列表来遍历, 例如用 foreach 语句。默认情况下,所有可见属性都将被用于遍历。

<?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:<br>";
        foreach ($this as $key => $value)
        {
            print '$key=>' . $key . "<br>";
            print '$value=>' . $value . "<br>";
        }
    }
}

$class = new MyClass();
$class->iterateVisible();

foreach ($class as $key => $value)
{
    print '$key=>' . $key . "<br>";
    print '$value=>' . $value . "<br>";
}

Final 关键字

PHP 5 新增了一个 final 关键字。如果父类中的方法被声明为 final,则子类无法覆盖该方法。 如果一个类被声明为 final,则不能被继承。

<?php

class BaseClass
{
    public function display()
    {
        echo 'final';
    }

    final public function test()
    {
        echo 'Hello World!';
    }
}

class A extends BaseClass
{
    public function display()
    {
        echo 'A';
    }

    public function test()
    {
        echo 'haha';
    }
}

$temp = new A();
$temp->test();
#会报错,final方法不能重写

对象复制

在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但有一个情况下确实需要:如果你有一个 GTK 窗口对象,该对象持有窗口相关的资源。

你可能会想复制一个新的窗口,保持所有属性与原来的窗口相同,但必须是一个新的对象(因为如果不是新的对象,那么一个窗口中的改变就会影响到另一个窗口)。

还有一种情况:

如果对象 A 中保存着对象 B 的引用,当你复制对象 A 时,你想其中使用的对象不再是对象 B 而是 B 的一个副本,那么你必须得到对象 A 的一个副本。

对象比较

当使用比较运算符(==)比较两个对象变量时,比较的原则是:

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

而如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)。

类型约束

PHP 5 可以使用类型约束。

如果一个类或接口指定了类型约束,则其所有的子类或实现也都如此。

类型约束不能用于标量类型如 int 或 string。Traits 也不允许。

<?php

class MyClass
{
    public function test_class(OtherClass $otherclass)
    {
        echo $otherclass->var;
        echo "<br>";
    }

    public function test_array(array $input_array)
    {
        print_r($input_array);
    }
}

class OtherClass
{
    public $var = 'Hello World!';
}

$myclass    = new MyClass();
$otherclass = new OtherClass();
$myclass->test_class($otherclass);

$input_array = ['one' => 'first', 'two' => 'second'];
$myclass->test_array($input_array);

后期静态绑定

自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。

self:: 的限制

使用 self:: 或者 CLASS 对当前类的静态引用,取决于定义当前方法所在的类:

后期静态绑定的用法

<?php

class A
{
    public static function who()
    {
        echo __CLASS__;
    }
    public static function test()
    {
//        self::who(); // 输出A
        static::who(); // 输出B
    }
}

class B extends A
{
    public static function who()
    {
        echo __CLASS__;
    }
}

$temp = new B();
$temp::test();

对象和引用

在php5 的对象编程经常提到的一个关键点是“默认情况下对象是通过引用传递的”。

但其实这不是完全正确的。下面通过一些例子来说明。

PHP 的引用是别名,就是两个不同的变量名字指向相同的内容。 在 PHP 5,一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容。 当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系, 只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

<?php

class A
{
    public $foo = 1;

}

$a = new A();
$b = $a;

$b->foo = 2;
echo $a->foo . "\n"; // 输出为2

对象序列化

序列化对象 - 在会话中存放对象

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。 unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

<?php
//
//include("class.inc");
//
//$a = new A();
//$a->show_one();
//
//$s = serialize($a);
//file_put_contents('store', $s);

// 反序列化必须要包含此文件。
include("class.inc");
$s = file_get_contents('store');
$a = unserialize($s);

$a->show_one();

命名空间

  1. 解决PHP内部的类、函数、常量或第三方类、函数、常量之间的名字冲突。
  2. 为很长的标识名称创建一个别名,提高源代码的可读性。
<?php

namespace my\name;

class MyClass{}

function myfunction(){}

const MYCONST = 1;

$a = new MyClass();
$c = new \my\name\MyClass;
$a = strlen('hi');
$d = namespace\MYCONST;
$d = __NAMESPACE__ . '\MYCONST';
echo $d;
echo constant($d);

定义命名空间

虽然任意合法的PHP代码都可以包含在命名空间中,但只有以下类型的代码受命名空间的影响,它们是:

类、接口、函数和常量。

命名空间通过关键字namespace来声明。如果一个文件中包含命名空间,它必须在其它代码之前声明命名空间, 有一个除外:declare关键字。

<?php

namespace space\MyProject;

const CONNECT_OK = 1;

class Connection{}
function connect(){}

echo __NAMESPACE__;

在同一个文件中定义多个命名空间

在同一个文件中定义多个命名空间有两种语法形式。

不建议使用这种语法在单个文件中定义多个命名空间,区间会显得不明确。

<?php

namespace MyProject;

const CONNECT_OK = 1;
class Connection
{
}

function connect()
{
}

echo __NAMESPACE__ . "<br>";

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection
{
}

function connect()
{
}

echo __NAMESPACE__ . "<br>";
// 不建议使用这种语法在单个文件中定义多个命名空间,区间会显得不明确。

使用大括号来定义多个命名空间

<?php

namespace MyProject
{
    const CONNECT_OK = 1;
    class Connection
    {
    }

    function connect()
    {
    }

    echo __NAMESPACE__ . "<br>";
}

namespace AnotherProject
{
    const CONNECT_OK = 1;
    class Connection
    {
    }

    function connect()
    {
    }

    echo __NAMESPACE__ . "<br>";

}

使用命名空间:别名、导入

允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。

<?php

namespace MyProject
{
    const CONNECT_OK = 1;
    class Connection
    {
        public function __construct()
        {
            echo "MyProject __construct" . "<br>";
        }
    }

    function connect()
    {
        echo "MyProject connect" . "<br>";
    }

    echo __NAMESPACE__ . "<br>";
}

namespace AnotherProject
{
    const CONNECT_OK = 1;
    class Connection
    {
        public function __construct()
        {
            echo "AnotherProject __construct" . "<br>";
        }
    }

    function connect()
    {
        echo "AnotherProject connect" . "<br>";
    }

    $temp = new \MyProject\Connection();
    use \MyProject as A;
    $temp = new A\Connection();
    use \Myproject\Connection as AConnection;
    $temp = new AConnection();

    echo __NAMESPACE__ . "<br>";
}

全局空间

如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与PHP引入命名空间概念前一样。

在名称前加上前缀"\"表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。

<?php

namespace www\web;

class MyClass
{
    public function display()
    {
        try
        {
            echo 'Hello World!';
        }
        catch (\Exception $e)
        {
            echo 'try...catch';
        }
    }
}

$temp = new MyClass();
$temp->display();

使用命名空间:后备全局函数/常量

在一个命名空间中,当PHP遇到一个非限定的类、函数或常量名称时,它使用不同的优先策略来解析该名称。

类名称总是解析到当前命名空间中的名称。因此在访问系统内部或不包含在命名空间中的类名称时,必须使用完全限定名称。

对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP会退而使用全局空间中的函数或常量。

<?php

namespace A\B\C;

class Exception extends \Exception
{
}

$a = new Exception('message');
$b = new \Exception('message');

echo strlen('Hello World!'); // 正常输出12
$c = new ArrayObject(); // 致命错误,找不到A\B\C\ArrayObject类

命名空间名称解析规则

命名空间名称定义

  • 非限定名称Unqualified name

名称中不包含命名空间分隔符的标识符,例如Foo

  • 限定名称Qualified name

名称中含有命名空间分隔符的标识符,例如Foo\Bar

  • 完全限定名称Fully qualified name

名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如\Foo\Bar。

生成器

生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现Iterator接口的方式,性能开销和复杂性大大降低。

生成器允许你在foreach代码块中写代码来迭代一组数据而不需要在内存中创建一个数组,在内存中创建一个大数组可能会使你的内存达 到上限,或者会占据可观的处理时间。

生成器函数,就像一个普通的自定义函数一样,和普通函数只返回一次不同的是,生成器可以根据需要yield多次,以便生成需要迭代的值。

一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值, 然后返回该数组, 结果就是会产生多个很大的数组。 比如,调用 range(0, 1000000) 将导致内存占用超过 100 MB。

<?php

function xrange($start, $end, $step = 1)
{
    for ($i = $start; $i <= $end; $i += $step)
    {
        yield $i;
    }
}
// 直接报500错误
foreach (range(0, 1000000) as $val)
{
    echo $val;
}
// 进入大循环
foreach (xrange(0, 1000000) as $val)
{
    echo $val;
}

生成器语法

我的理解就是链表来的,一个指针像游标一样,循环迭代。

一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。

当一个生成器被调用的时候,它返回一个可以被遍历的对象。当你遍历这个对象的时候PHP将会在每次需要值的时候调用生成器函数, 并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。

yield关键字

生成器函数的核心就是yield关键字。它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并 终止函数的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。

<?php

function test()
{
    for ($i = 0; $i <= 10; $i++)
    {
        // 注意:变量$i的值在不同的yield之间是保持传递的。
        yield $i;
    }
}

$temp = test();
foreach ($temp as $value)
{
    echo "$value" . "<br>";
}

指定键名来生成值

<?php

$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;

function input_parse($input)
{
    foreach (explode("\n", $input) as $line)
    {
        $fields = explode(';', $line);
        $id     = array_shift($fields); // array_shift将数组开头的单元移出数组

        yield $id => $fields;
    }
}

foreach (input_parse($input) as $key => $value)
{
    echo '$key=>' . $key . "<br>";
    echo '$value=>' . print_r($value) . "<br>";
}

生成null值

yield可以在没有参数传入的情况下被调用来生成一个NULL值并配对一个自动的键名。

可以使用生成器来初始化一个null数组。

<?php

function test()
{
    foreach (range(1, 3) as $i)
    {
        yield;
    }
}
var_dump(iterator_to_array(test()));

使用引用来生成值

生成函数可以像使用值一样来使用引用生成。

<?php

function &test()
{
    $value = 10;

    while ($value > 0)
    {
        yield $value;
    }
}

foreach (test() as &$value)
{
    echo (--$value) . '...';
}

PHP中的引用

在PHP中引用意味着用不同的名字访问同一个变量内容。这并不像C的指针: 例如你不能对他们做指针运算,他们并不是实际的内存地址。

在PHP中,变量名和变量的内容是不一样的,因此同样的内容可以有不同的名字。

$a = 'Hello world!';
$b = &$a;
$b = 'new Hello world!';
//echo $a;

function test(&$temp){
    $temp = 'function Hello world!';
}
test($b);
echo $a;

引用返回

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。

不要用返回引用来增加性能,引擎足够聪明来自己进行优化。

仅在有合理的技术原因时才返回引用!要返回引用,请看如下示例:

class temp
{
    public $value = 100;

    public function &getValue()
    {
        return $this->value;
    }
}

$obj   = new temp();
$value = &$obj->getValue();
echo $value . '<br>'; // 输出100
$obj->value = 9;
echo $value . '<br>'; // 输出9

取址引用

当unset一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。

$a = 1;
$b = &$a;
unset($a);

引用定位

许多PHP的语法结构 是通过引用机制实现的,所以上述有关引用绑定的一切也都适用于这些结构。

global引用

当用global $var声明一个变量时实际上建立了一个到全局变量的引用。

global $var;
$var = & $GLOBALS['var']; // 与上一行代码是等价的。

$this

在一个对象的方法中,$this永远是调用它的对象的引用。

php如何使用类

class myclass{
    //成员变量(公有访问控制)
    public $myvar;
    //构造函数
    function __construct($myvar){
        $this->myvar = $myvar;
    }
    //封装
    function setValue($myvar){
        $this->myvar = $myvar;
    }
    function getValue(){
        return $this->myvar;
    }
    //析构函数
    function __destruct(){
        unset($this->myvar);
    }
}
//类继承
class myextends extends myclass{
}
$myclass = new myextends("Moments");
echo $myclass->getValue();
  • 如何使用静态变量
class myclass{
    //使用静态变量
    public static $myvar = "Moments";
    public function myfun(){
        return self::$myvar;
    }
}
$myclass = new myclass();
echo myclass::$myvar;
echo $myclass->myfun();        
  • 如何使用抽象类
abstract class myclass{
    public $myvar;
    //强制要求子类定义之些方法
    abstract protected function setValue($myvar);
    //普通方法
    public function getValue(){
        return $this->myvar;
    }
}
class myextends extends myclass{
    function setValue($myvar){
        $this->myvar = $myvar;
    }
    function getValue(){
        return parent::getValue();
    }
}
$myclass = new myextends();
$myclass->setValue("Moments");
echo $myclass->getValue();      
  • 如何使用对象接口
#接口中定义的所有方法都必须是公有
interface myinterface{
    //接口不支持成员变量,可以使用常量
    const myconst = "myconst";
    //类中必须实现接口中定义的所有方法。
    public function setValue($myvar);
    public function getValue();
}
class myextends implements myinterface{
    public function setValue($myvar){
        $this->myvar = $myvar;
    }
    public function getValue(){
        return $this->myvar;
    }
}
$myclass = new myextends();
$myclass->setValue("Moments");
echo $myclass->getValue();
echo myinterface::myconst;