Static 关键字
声明类成员或方法为 static
,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this
在静态方法中不可用。静态属性不可以由对象通过 ->
操作符来访问。
注意:在 PHP7 中通过(::)调用非静态方法会产生一个 E_DEPRECATED 级别的警告,不赞成这样使用,在以后可能会取消对这种用法的支持。
<?php
class Test
{
public $hi = 'Hi';
public static $hello = 'Hello';
public function sayHi()
{
echo $this->hi;
}
public static function sayHello()
{
echo self::$hello;
}
public function sayWorld()
{
echo " World".PHP_EOL;
}
}
$obj = new Test();
$obj->sayHi();
$obj->sayWorld();
Test::sayHello();
Test::sayWorld();
从结果可以看出
- 通过
::
可以执行静态和非静态方法,但是不赞成通过这种方式调用非静态方法,此方式有可能被官方移除,因此上面sayWorld()
,应该通过(new Test())->sayWorld()
这种方式调用 - 静态属性和方法可以通过
self
关键字调用
就像其它所有的PHP静态变量一样,静态属性只能被初始化为一个字符值或一个常量,不能使用表达式。 所以你可以把静态属性初始化为整型或数组,但不能指向另一个变量或函数返回值,也不能指向一个对象。
抽象类
定义为抽象的类可能无法直接被实例化,任何一个类, 如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。如果类方法被声明为抽象的, 那么其中就不能包括具体的功能实现。
<?php
abstract class Say
{
abstract public function sayHello($word);
abstract public function sayHi();
}
class Speak extends Say
{
public function sayHello($word)
{
echo "Hello $word";
}
public function sayHi()
{
echo "Hi".PHP_EOL;
}
}
$s = new Speak();
$s->sayHi();
$s->sayHello("World");
从结果可以看出
- 继承一个抽象类的时候,子类必须定义父类中的所有抽象方法。例如,在类 Speak 中移除方法 sayHi(),结果为
Fatal error: Class Speak contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Say::sayHi)...
- 这些方法的访问控制必须和父类中一样(或者更为宽松)。例如,在类 Speak 中 sayHi() 声明为 protected,则报错
Fatal error: Access level to Speak::sayHi() must be public (as in class Say)...
- 此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,移除抽象方法 sayHello() 中的参数,则
Fatal error: Declaration of Speak::sayHello($word) must be compatible with Say::sayHello()...
接口
使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。我们可以通过 interface 来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。 接口中定义的所有方法都必须是public,这是接口的特性。
实现
要实现一个接口,可以使用 implements
操作符。类中必须实现接口中定义的所有方法,否则会报一个 fatal 错误。如果要实现多个接口,可以用逗号来分隔多个接口的名称。
<?php
interface A
{
public function actionA();
}
interface B
{
public function actionB();
}
//实现多个接口
class C implements A, B
{
public function actionA()
{
//do something
}
public function actionB()
{
//do something
}
}
注意:
- 实现多个接口时,接口中的方法不能有重名。
- 接口也可以继承,通过使用 extends 操作符。
常量
接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。
<?php
interface A
{
const B = 'Interface constant';
}
// 输出接口常量
echo A::B;
// 错误写法,因为常量的值不能被修改。接口常量的概念和类常量是一样的。
class C implements A
{
const B = 'Class constant';
}
匿名类
php7支持通过new class
来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>
网友评论