PHP 中用 class
来定义类,用 new
来实例化对象,用 extends
继承类,不过只能单继承。属性和方法有 public
、private
和 protected
做访问控制,默认为 public,在类里定义常量不需要 $
,用(::
)范围解析符可以调用父类的方法,访问类的静态变量、静态方法和常量。
PHP 命名空间 namespace
--------------------------------------------------------------
构造方法 void __constuct()。注意: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用parent::__construct()。
class Hello{
/**
* Hello constructor.
* @param $age 年龄/int
* @param $name 名字/srting
*/
public function __construct($age,$name) // 构造方法
{
$this->_age = $age;
$this->_name = $name;
}
public function getAge(){
return $this->_age;
}
public function getName(){
return $this->_name;
}
private $_age,$name;
}
$h = new Hello(10,'我'); // 创建实例
$h->sayHello();
析构函数
void __destruct( void )
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
<?php class A { public function __construct() { echo 'Start...'; } public function sayHi() { echo "Hi..."; } public function __destruct() { echo "Finish"; } } (new A())->sayHi(); // Start...Hi...Finish
--------------------------------------------------
成员方法与类方法
static
class Hello{ /** * Hello constructor. * @param $age 年龄/int * @param $name 名字/srting */ public function __construct($age,$name) // 构造方法 { $this->_age = $age; $this->_name = $name; Hello::$NUM++; if(Hello::$NUM>Hello::MAX_MAN_NUM){ throw new Exception('不能'); } } public function getAge(){ return $this->_age; } public function getName(){ return $this->_name; } private $_age,$name; private static $NUM = 0; // 静态变量 const MAX_MAN_NUM = 200; //常量 // 都是描述类的 public static function sayHello(){ echo '类'; } } $h = new Hello(10,'我'); // 创建实例 $h->sayHello();
---------------------------------
定义
类的变量成员叫做属性
。属性声明是由访问控制关键字 public
,protected
或 private
和一个变量来组成,同时可以加上默认值。
<?php class A { //只能在类本身使用 private $a = "Hello"; //可以在子类和类本身使用 protected $b = <<<EOT This is variable b; EOT; //除了子类,类本身,外部也可以访问 public $c; }
访问属性
在类的成员方法里面,可以通过 $this->
加变量名来访问类的属性和方法,但是要访问类的静态属性或者在静态方法要使用 self::
加变量名。
注意 self::
这种方式后的变量名需要加 $
符号,而 $this->
后的变量名不需要加
<?php class A { private $a = "Hello"; protected $b = <<<EOT This is property b EOT; public static $c = 'This is a'.' static property'; public function talk() { echo $this->a.PHP_EOL; echo $this->b.PHP_EOL; echo self::$c; } } (new A())->talk();
---------------------------------------------
类的继承
extends
方法重写.可以修改方法内的功能
class A { } class B extends A { }
被继承的方法和成员可以通过用同样的名字重新声明被覆盖,除非父类定义方法时使用了 final
关键字。可以通过 parent::
来访问被覆盖的方法或成员。
--------------------------------------------
访问控制
对属性或方法的访问控制,是通过在前面添加关键字 public、protected 或 private 来实现的。如果未添加,则默认为 public。
public
所定义的类成员可以在任何地方被访问protected
所定义的类成员则可以被其所在类的子类和父类访问(当然,该成员所在的类也可以访问)private
定义的类成员则只能被其所在类访问
---------------------------------------------
范围解析操作符,可以简单地说是一对冒号,可以用于访问静态成员、方法和常量,还可以用于覆盖类中的成员和方法。
当在类的外部访问这些静态成员、方法和常量时,必须使用类的名字。
<?php class A { const CONST_A = 'A constant value'; public static function sayHello() { echo 'Hello'; } } class B extends A { public static $b = 'static var b'; /** * 覆盖父类方法 * */ public static function sayHello() { echo parent::sayHello().' World'.PHP_EOL; } public static function actionB() { self::sayHello(); echo parent::CONST_A.PHP_EOL; echo self::$b; } } B::actionB();
-------------------------------------------------
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()...
-----------------------------------------
接口
接口中定义的所有方法都必须是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 { public function actionA(); } interface B extends A { public function actionB(); } class C implements A { public function actionA() { //do something } public function actionB() { //do something } }
常量
接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。
<?php interface A { const B = 'Interface constant'; } // 输出接口常量 echo A::B; // 错误写法,因为常量的值不能被修改。接口常量的概念和类常量是一样的。 class C implements A { const B = 'Class constant'; }
---------------------------------------------
时间和日期
time()
date_default_timezone_set('Asia/Shanghai'); // 设置时区 不然... echo date('Y-m-d H:i:s',time());