6.3. 类的其它特性
持之以恒,方得始终!
类常量 const
class Math {
const PI = 3.14;
}
echo Math::PI;
我们可以看到,直接用类去访问常量,可见,常量是属于类的。
为什么有类常量?其实还是为了更好的封装性,在现在的oop编程中,基本都是在类里面写代码的。
类静态方法 static
class Math {
static function squared($input) {
return $input*$input;
}
}
echo Math::squared(8);
可以看到,静态方法也是直接用类去调用的,所以,它也是属于类的。
还有注意,它里面不能包含对象的引用,比如$this
,因为类直接调用的情况下,它没有一个实例对象能引用的。
instanceof
- 可以检查一个对象,是否是某个类的实例。
- 可以检查一个对象的类,是否是从某个类继承来的。
- 可以检查一个对象的类,是否实现了某个接口。
class A {}
class B extends A {}
interface Displayable{}
$b = new B();
var_dump($b instanceof B); // bool(true) $b对象是否是类B的实例
var_dump($b instanceof A); // bool(true) $b对象的类,是否继承自类A
var_dump($b instanceof Displayable); // bool(false) $b对象的类,是否实现接口Displayable
函数中,对象参数
function check_hint(B $someclass) {
...
}
上面的函数,要求 $someclass 必须是 类B 的实例。或者继承了类B的类的实例。
如果传入类A的实例,则报错:
$a = new A();
check_hint($a); // Fatal error ...
如果是这样 function check_hint(A $someclass)
,要求类A的实例,我们给B类的实例,则不报错,因为B类继承了A类。
延迟静态绑定
子类中,重写父类的静态方法。
子类调用到了这个静态方法时,访问的是自己重写的。
class A {
public static function who() {
var_dump("111111");
echo __CLASS__ . PHP_EOL;
}
public static function test() {
static::who();
}
}
class B extends A {
// 重写了父类的静态方法
public static function who() {
var_dump("222222");
echo __CLASS__ . PHP_EOL;
}
}
A::test();
// string(6) "111111"
// A
B::test();
// string(6) "222222"
// B
克隆对象 clone
复制一个已有的对象
$c = clone $b; // 创建一个与$b一样的副本
__clone()
魔术方法,在被 clone 时,会自动调用,因此我们就可以用它做一些预处理的事情。比如修改属性。
抽象类,抽象方法
抽象类不能被实例化,同时,它的类方法也没有被实现,只是提供了一个类方法的声明。
abstract class A { // 抽象类
abstract function operation($param1, $param2); // 抽象方法
}
主要作用其实可接口类差不多,相当于leader写好一个要实现的功能的类模板,手下的人写个类继承后,去重写里面的抽象方法。
abstract class A {
abstract function add($n1, $n2);
}
class B extends A {
public function add($n1, $n2) {
return $n1 + $n2;
}
}
$b = new B();
echo $b->add(1,11);
__call()
前面已经使用了很多魔术方法了,回顾一下 __get(), __set(), __construct(), __destruct(), __clone()
,他们都是特定条件下,会自动触发。__call()
当然也是这样。
__call()
当调用一个类中没有的方法时,会自动执行它。
__call()
方法必须带有两个参数,第一个是调用的方法的名称,第二个是调用方法给的参数数组。
class A {
public function __call($method, $param) {
var_dump($method, $param);
if ($method == 'display') {
if (is_object($param[0])) {
$this->displayObject($param[0]);
} elseif (is_array($param[0])) {
$this->displayArray($param[0]);
} else {
$this->displayScalar($param[0]);
}
}
}
protected function displayObject() {
var_dump("displayObject is use...");
}
protected function displayArray() {
var_dump("displayArray is use...");
}
protected function displayScalar() {
var_dump("displayScalar is use...");
}
}
$a = new A();
$a->display([1,2,3]);
$a->display('cat');
/* string(7) "display"
array(1) {
[0]=>
array(3) {
[0]=>int(1)
[1]=>int(2)
[2]=>int(3)
}
}
string(22) "displayArray is use..."
string(7) "display"
array(1) {
[0]=>string(3) "cat"
}
string(23) "displayScalar is use..." */
上面代码的意思是,如果调用一个A类中没有的display()方法,则会触发__call()
魔术方法,它里面根据请求的方法名称,再根据参数类型,决定最终要访问的方法是谁。
__autoload()
这是一个特殊函数,不是在类里面定义的。
它的作用是,在 new 一个对象时,如果这个类没有在当前脚本中声明,则会自动执行它。
一般的做法是,将需要的类声明文件包含进来。
function __autoload($classname) {
include_once($classname . ".php");
}
类转为字符串 __toString()
如果在类中,实现了 __toString()
方法,当打印该类时,自动调用这个方法。
class A {
public $testone;
public $testwo;
public function __toString() {
return var_export($this, true);
}
}
$a = new A;
echo $a;
如有任何侵权行为,请通知我删除,谢谢大家!
个人邮箱:865460609@qq.com
推荐文章: