0210作业-命名空间-php培训十期线上班
一. 编程题:
1. 实例演示完全限定名称访问四类全局成员的方式
1.1 基本知识点
- 全局成员: 类, 接口, 函数, 常量
- 全局空间: 用反斜线来表示
\
, 根目录 - 完全限定名称: 从全局空间开始查找成员, 类似绝对路径
- 限定名称: 从当前空间开始查找成员, 类似相对路径
- 非限定名称: 仅在当前空间中查找成员, 类似当前路径
- 四类全局成员:接口、类、函数、常量
- define()定义的常量是全局的,不受命名空间影响
1.2 实例展示完全限定名称访问四类全局成员
- 访问接口
namespace part1;
{
//定义一个接口
interface iTest{
public function info();
}
}
namespace part2;
{
//用完全限定名称来访问part1中定义的接口
class cTest1 implements \part1\iTest{
public function info(){
return '实现接口的类';
}
}
$obj1 = new cTest1();
echo $obj1->info();
echo '<hr>';
}
- 访问类
namespace part1\lib;
{
//实现接口的类
class cTest implements \part1\iTest {
public function info(){
return [
'namespace'=>__NAMESPACE__,
'classname'=>__CLASS__,
'classname1'=>self ::class,
'methode'=>__METHOD__,
];
}
}
}
namespace part2;
{
//演示用完全限定名称访问part1中的类
$obj = new \part1\lib\cTest();
$arr = $obj->info();
echo '<pre>'.print_r($arr,true).'</pre>';
echo '<hr>';
}
访问函数
namespace part1\common;
{
//定义一个函数
function ftest(){
return '函数已运行';
}
}
namespace part2;
{
//演示用完全限定名称访问part1中的函数
$result = call_user_func('\part1\common\ftest');
echo '用完全限定名称访问函数:'.$result;
echo '<hr>';
}
访问常量
//注意此处命名空间的写法,这里没有用{}将内容包含住,一旦放入{}中const定义的常量会报错
namespace part1\param;
//定义一个常量
define('URL','www.php.cn');
const SITE_NAME = 'php中文网';
namespace part2;
{
//演示用完全限定名称访问part1中的常量
//因为URL是用define()定义的,因此不受命名空间影响,应该用全局空间
$url1 = URL;
$url2 = \URL;
$name = \part1\param\SITE_NAME;
echo '无完全限定名称的前缀\'\\\'访问define()定义的常量URL:'.$url1;
echo '<hr>';
echo '只有完全限定名称的前缀\'\\\'访问define()定义的常量URL:'.$url2;
echo '<hr>';
echo '需用整个完全限定名称访问const定义的常量URL:'.$name;
}
2. 实例演示导入四类全局全局成员的方式
- 导入接口
namespace part1;
{
//定义一个接口
interface iTest{
public function info();
}
}
namespace part2;
//用use导入part1中定义的接口
use \part1\iTest;
class cTest1 implements iTest{
public function info(){
return '实现接口的类';
}
}
$obj1 = new cTest1();
echo $obj1->info();
echo '<hr>';
- 导入类
namespace part1\lib;
{
//实现接口的类
class cTest implements \part1\iTest {
public function info(){
return [
'namespace'=>__NAMESPACE__,
'classname'=>__CLASS__,
'classname1'=>self ::class,
'methode'=>__METHOD__,
];
}
}
}
namespace part2;
//用use导入part1中的类
use \part1\lib\cTest;
$obj = new cTest();
$arr = $obj->info();
echo '<pre>'.print_r($arr,true).'</pre>';
echo '<hr>';
- 导入函数
namespace part1\common;
{
//定义一个函数
function ftest(){
return __FUNCTION__;
}
}
namespace part2;
//用use function导入part1中的函数
use function \part1\common\ftest;
$result = ftest();
// echo $n =call_user_func('ftest');
echo '<hr>';
echo $m =call_user_func('\part1\common\ftest');
echo '<hr>';
echo '通过use function导入,来访问函数:'.$result;
echo '<hr>';
- 导入常量
namespace part1\param;
//定义一个常量
define('URL','www.php.cn');
const SITE_NAME = 'php中文网';
namespace part2;
//用use const导入part1中的常量
//因为URL是用define()定义的,因此不受命名空间影响,应该用全局空间
use const URL,SITE_NAME;
$url1 = URL;
$url2 = \URL;
$name = \part1\param\SITE_NAME;
echo '通过use const导入,来访问define()定义的常量URL:'.$url1;
echo '<hr>';
echo '通过use const导入,来访问define()定义的常量URL:'.$url2;
echo '<hr>';
echo '通过use const导入,来访问const定义的常量URL:'.$name;
3. 实例演示全局成员中的别名引用方式
- 接口的别名引用方式
namespace part1;
{
//定义一个接口
interface iTest{
public function info();
}
}
namespace part2;
//用use导入part1中定义的接口
use \part1\iTest as iT;
class cTest1 implements iT{
public function info(){
return '实现接口的类';
}
}
$obj1 = new cTest1();
echo $obj1->info();
echo '<hr>';
- 类的别名引用方式
namespace part1\lib;
{
//实现接口的类
class cTest implements \part1\iTest {
public function info(){
return [
'namespace'=>__NAMESPACE__,
'classname'=>__CLASS__,
'classname1'=>self ::class,
'methode'=>__METHOD__,
];
}
}
}
namespace part2;
//用use导入part1中的类
use \part1\lib\cTest as cT;
$obj = new cT();
$arr = $obj->info();
echo '<pre>'.print_r($arr,true).'</pre>';
echo '<hr>';
- 函数的别名引用方式
namespace part1\common;
{
//定义一个函数
function ftest(){
return __FUNCTION__;
}
}
namespace part2;
//用use function导入part1中的函数
use function \part1\common\ftest as ft;
$result = ft();
// echo $n =call_user_func('ftest');
echo '<hr>';
echo $m =call_user_func('\part1\common\ftest');
echo '<hr>';
echo '通过use function导入,来访问函数:'.$result;
echo '<hr>';
- 常量的别名引用方式
//注意此处命名空间的写法,这里没有用{}将内容包含住,一旦放入{}中const定义的常量会报错
namespace part1\param;
//定义一个常量
define('URL','www.php.cn');
const SITE_NAME = 'php中文网';
namespace part2;
//用use const导入part1中的常量
//因为URL是用define()定义的,因此不受命名空间影响,应该用全局空间
use const URL as UL;
// use const SITE_NAME as SN; //这样导入使用别名不成功
$url1 = UL;
// $name = SN;
echo '通过use const导入,来访问define()定义的常量URL:'.$url1;
echo '<hr>';
二. 问答题:
1. 完全限定名称, 限定名称与非限定名称
- 我理解的的完全限定名称,限定名称和非限定名称,就类似于windows系统中的文件夹,这样虽然两个文件会同名,但是只要不在一个文件夹中,就没有关系,只是、只是、只是这里是类比,具体的定义命名空间的php文件怎么存放和命名空间中定义的子集是不相关的,那个只涉及到
require
和include
具体文件。- 完全限定名称,就像是绝对路径,必须以’\’开头(use导入时是默认的可以省略),其前缀’\’就类似于是电脑系统中的盘符C:或者D:之类的。这个符号的意义在于,电脑解析你的命名空间时,看见了它就不会在前面去添加其他的东西了,也就是告诉电脑这是根目录了。
- 限定名称,就像是相对路径,其特征是最开始没有前缀’\’,如果你想调用子目录命名空间的全局成员时,可以选择这种方式。其原理就是电脑在解析限定名称时会将当前代码的命名空间加在前面。
例如:namespace part1\lib;
{
//实现接口的类
class cTest implements \part1\iTest {
public function info(){
return [
'namespace'=>__NAMESPACE__,
'classname'=>__CLASS__,
'classname1'=>self ::class,
'methode'=>__METHOD__,
];
}
}
}
namespace part1;
$obj5 = new lib\cTest();//这里会被解析成为part1\lib\cTst
$arr = $obj5->info();
print_r($arr);
- 非限定名称,代表着当前代码的命名空间,只能在自己的命名空间中使用,是不能跨不同的命名空间使用的。
2. 完成限定名称与限定名称, 非限定名称之间的转换方式
- 我理解的转换,是通过use导入达成的。在use导入时不将命名空间的路径写全,只写了上面几层目录,这样就实现了在代码中用限定名称来使用。如果在use导入时将命名空间的路径写全,那么就实现了非限定名称来使用。
3. use 解决了什么什么?
- use解决了完全限定名称、限定名称和非限定名称之间的转换,简化了在代码编写中反复写完全限定名称或限定名称的工作。
4. ::class操作符为什么比NAMESPACE好用? 具体应用场景有哪些?
::class
操作符代表的是完全限定名称,__NAMESPACE__
常量代表的是非限定名称,::class
可以在别的命名空间中使用,而__NAMESPACE__
不行。类名::class
,这样就可以得到一个带完全限定名称的类名了,然后再怎么用不是很清楚。