php类与对象

类与对象

一个类可以包含有属于自己的常量,变量(称为”属性”)以及函数(称为”方法”)

声明

类的声明如下:

class 类名
{

}

属性和方法的访问修饰符:

有以下几种访问修饰符:

  • public 共有的,由public修饰的属性和方法可以在类里面、类外面、子类里面访问
  • protected 受保护的,由protected修饰的属性和方法 能够在类里面和子类里面访问
  • private 私有的 由protected修饰的属性和方法只能在类里面访问
  • static 静态,声明类属性或方法为静态,就可以不实例化类而直接访问;定义静态则不管是否使用,都会占用空间

例子

在一个类的内部使用本类的属性或方法时可使用$this

<?php

class Test //定义类
{
    public $name; //公有属性
    //$this->shuchu(); //调用shuchu()方法
    function shuchu() //方法
    {
        echo $this->name; //输出属性$name
    }
}

$a = new Test(); //要创建一个类的实例,必须使用 new 关键字
$a->name='hello'; //将属性赋值为'hello'
$a->shuchu(); //调用方法,输出hello
?>
  • $this 代表当前对象
  • self 代表当前类
  • parent 代表父类

调用方式:

  • -> 用类的实例调用对象
  • :: 可以用类直接调用属性和方法

继承

如果一个类扩展了另一个,则父类必须在子类之前被声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

class foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}

public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}

class bar extends foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}

$foo = new foo();
$bar = new bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP(); // Output: 'PHP is great'
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP(); // Output: 'PHP is great'

?>

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

魔法方法

魔法方法都有个自动调用的功能;魔法方法开头有两个下划线

__toString()

方法用于一个对象被当成字符串时应怎样回应。

如:

?php

class Test
{
    public $name;
    function __tostring()
    {
        return 'you are wrong!';
    }
}

$a = new Test();
var_dump($a);
echo '<br>';
echo $a;
?>

运行显示

注:该方法要有个返回值

__sleep() 与 __wakeup()

serialize()函数会检查类中是否存在一个魔法方法__sleep(),如果存在,该方法会先被调用

unserialize()函数会检查类中是否存在__wakeup(),如果存在,该方法会先被调用

__construct() 与 __destruct()

__construct():
具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。

__destruct():
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

可以使用unset()来人为主动销毁一个对象;当一个对象没有变量指向它的时候,就会被销毁,如果不销毁,则系统在程序运行完全结果后,会去销毁对象;并且此时销毁的顺序跟其创建的顺序相反

__sleep()、__wakeup()、__construct()与 __destruct() 执行顺序

<?php
class user {
    function __construct() { 
        echo 'make'."<br>";
        }

    function __wakeup() {
        echo 'wake'."<br>";
        }

    function __destruct() {
        echo 'destroy'."<br>";
        }

    function __sleep() {      
        echo 'sleep'."<br>";
        return(array('name'));
        }
    }

$u = new user();
$u->name = "Leo";
$s = serialize($u); 
echo $s;
echo "<br>";
$u2 = unserialize($s); 
?>

__call()

在对象中调用一个不可访问的方法时,__call()会被调用

__invoke()

尝试以调用函数的方式调用一个对象时,__invoke()方法会被自动调用(PHP>=5.3.0)

__set()

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

__get()

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

__isset()

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

__unset()

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

接口与实现

可以使用接口来指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容;可以通过interface关键字定义接口;

可以通过implements操作符来实现一个接口;类中必须实现接口定义的所有方法,否则会报一个致命错误

example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php

// 声明一个'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 => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}

return $template;
}
}

// 下面的写法是错误的,会报错,因为没有实现 getHtml():
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();

public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
?>