Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:
- 描述类成员重载的原理与实现,并实例演示;
- 全局成员有哪几种,有什么特点,并实例演示;
- 实例演示空间的声明与空间成员的访问;
- 实例演示空间成员的分解与合并操作;
- 实例演示子空间,并在子空间中访问任何空间中的成员的方式;
PHP提供的“重载”是指动态的“创建”类属性和方法。是通过魔术方法来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。
所有的重载方法都必须被声明为 public。
在给不可访问属性赋值时,set() 会被调用。
读取不可访问属性的值时,get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,isset() 会被调用。
当对不可访问属性调用 unset() 时,unset() 会被调用。
参数$name是指要操作的变量名称。set()方法的$value参数指定了$name变量的值。
属性重载只能在对象中进行。在静态方法中这些魔术方法是无效的。因此,这些魔术方法都不能声明为static。
示例:使用get(),set(),isset()和__unset()进行属性重载
<?php
class Demo1
{
protected $data = [
'username' => 'liushuchang2007'
];
//属性重载
public function __get($name)
{
$method = 'get' . ucfirst($name);
return $this->$method($name);
}
// 获取器
public function getUsername($name)
{
if (!isset($this->data[$name])) {
$this->data[$name] = 0;
} else {
return $this->data[$name];
}
}
public function getEmail($name)
{
if(!isset($this->data[$name])) {
$this->data[$name] = 0;
} else {
return $this->data[$name];
}
}
public function __set($name, $value)
{
$method = 'set' . ucfirst($name);
return $this->$method($name,$value);
}
// 设置器
public function setEmail($name,$value)
{
$this->data[$name] = $value;
}
// 方法重载
// 普通方法:__call()
// 静态方法:__callStatic()
public function __call($name,$args)
{
// 请求转发
return $name . '[' . implode(',',$args) . ']';
}
// 当访问一个不存在的静态方法,会定位到下面这个魔术方法中
public static function __callStatic($name, $args)
{
return $name . '[' . implode(',',$args) . ']';
}
}
$obj = new Demo1;
echo $obj->username,'<br>';
$obj->email = 'liushuchang@sina.com.cn';
echo $obj->mail;
echo '<br>';
echo $obj->world(66,77,99);
echo '<br>';
echo Demo1::test('e','f','g');
图示:
PHP中的全局成员有:类(class),常量(const),函数(function);
全局成员的特点是:一旦定义就不能重复声明
<?php
// 类
class Love
{
public $love = __CLASS__;
}
echo (new love)->love.'这是类','<hr>';
// 常量
const PRYUE = 'You'.'你是常量吗';
echo PRYUE,'<hr>';
// 函数
function set()
{
return __FUNCTION__;
}
echo set().'函数','<hr>';
图示:
<?php
// 命名空间
namespace ns {
// 类
class Deom
{
}
// 常量
const PINGYING = '中国梦';
// 函数
function set()
{
}
echo Deom::class, '<br>';
echo PINGYING::class, '<br>';
echo set::class, '<br>';
}
// 全局空间
namespace {
echo '<hr>';
// 类
class Deom
{
}
// 常量
const PINGYING = '中国梦';
// 函数
function set()
{
}
echo Deom::class, '<br>';
echo PINGYING::class, '<br>';
echo set::class, '<br>';
}
图示:
demo6.php样式代码:
<?php
// 同名空间成员的组织方式
namespace NO;
require 'demo6-1.php';
require 'demo6-2.php';
require 'demo6-3.php';
// 类
echo Demo1::class, '<br>';
// 常量
echo Demo2::class, '<br>';
// 函数
echo Demo3::class, '<hr>';
demo6-1.php样式代码:
<?php
namespace NO;
// 类
class Demo1
{
// 我有500行代码
}
demo6-2.php样式代码:
<?php
namespace NO{
// 常量
//此处有800行代码
}
demo6-3.php样式代码:
<?php
namespace NO{
// 函数
// 此处1200行代码
}
合并后图示:
<?php
// 父空间
// namespace: 用在空间中,表示当前空间的引用,类似于$this或self
namespace nos1 {
class Name
{
// ...
}
echo Name::class, '<br>';
// 访问它的子空间成员
echo nos2\Name::class, '<br>';
echo nos2\nos3\Name::class, '<hr>';
}
// nos1的子空间
namespace nos1\nos2 {
class Name
{
// ...
}
echo Name::class, '<br>';
echo nos3\Name::class, '<hr>';
}
// nos2的子空间
namespace nos1\nos2\nos3 {
class Name
{
// ...
}
echo Name::class, '<br>';
// 在nos3中,访问上级空间怎么办?
echo \nos1\nos2\Name::class, '<br>';
echo \nos1\Name::class, '<br>';
// 全局成员:前面加上全局空间的标识符: \
echo \Name::class,'<hr>';
}
图示: