50

这两者有什么区别:

use Exception;
use \Exception;

或者那些:

use Foo\Bar;
use \Foo\Bar;

手册说:

请注意,对于命名空间名称(包含命名空间分隔符的完全限定的命名空间名称,例如 Foo\Bar,而不是不包含命名空间分隔符的全局名称,例如 FooBar),前导反斜杠是不必要且不允许的,因为导入名称必须是完全限定的,并且不相对于当前命名空间进行处理。

但我不太明白这一点,因为上述所有变体都有效,即它绝对不是“不允许的”。

研究zend_do_use表明,is_global(设置,当有前导反斜杠时)仅在以下情况下用于警告:

namespace {
    use Exception;
}

这告诉我:“使用非复合名称‘异常’的语句无效”。(虽然做同样的事情use \Exception会产生同样的影响,但不会发出警告。)

所以:我错过了什么吗?真的有什么区别吗?

4

5 回答 5

37

手册将反斜杠指定为不必要的,这自然意味着如果您仍然使用它,则含义是等效的。但是,正如您所指出的,该手册说它应该是不允许的,这是错误的。

但是,该手册还有其他问题。他们宣传这个:

// importing a global class
use \ArrayObject;

如果确实没有相对于当前命名空间处理导入名称,则use \ArrayObjectuse ArrayObject必须具有相同的含义。use ArrayObject除了全局,还有什么可以指代的?在实践中,引擎将导入全局引擎。

此外,还有这样的错误: http ://bugs.php.net/bug.php?id=49143

我相信人们对标准应该是什么感到困惑。

回答你的问题:没有区别。但是,如果我是引擎开发人员,同时也是无前导斜线标准的信徒,那么我就不需要考虑有人写use \Exception;. 我相信很可能就是这种情况。

于 2011-02-02T20:08:22.973 回答
15

事实上,目前在导入命名空间时使用前导反斜杠没有区别,而且PHP 手册中的信息也发生了变化:

请注意,对于命名空间名称(包含命名空间分隔符的完全限定的命名空间名称,例如 Foo\Bar 而不是不包含命名空间分隔符的全局名称,例如 FooBar),前导反斜杠是不必要的,也不推荐使用,因为导入名称必须是完全限定的,并且不相对于当前命名空间进行处理。

因此,现在有真实信息表明不建议使用前导反斜杠,但没有信息表明过去不允许使用反斜杠。

所以目前:

use Exception;
use \Exception;

这两条线的工作方式相同,但您应该使用第一条线。

于 2014-07-07T10:47:42.213 回答
6

通常前导反斜杠定义标识符是绝对的。如果它丢失,解释器假定它是一个相对标识符。

这是一个绝对标识符:

$x = new \Name\Space\To\Class();

这是一个相对标识符,因为没有前导斜杠。它相对于当前命名空间:

namespace Name\Space;
$x = new To\Class;

这也是一个相对标识符。在这种情况下,它针对该use语句解决,因为最后一部分(别名)与类的第一部分相同:

namespace Other\Name\Space;
use Name\Space;
$x = new Space\To\Class;

但是,因为 innamespaceuse语句只允许使用绝对标识符(完全限定名称),所以这里可以省略它。在namespace中,甚至不允许设置前导反斜杠。

有关 PHP 如何解析不同命名空间声明的更多信息,请参阅命名空间规则手册

于 2011-02-02T20:40:42.483 回答
-2

前导反斜杠表示全局命名空间。如果您在命名空间的范围内,则必须使用它来访问全局命名空间。例如:

namespace A
{
    class A
    {
        public function __construct()
        {
            echo('namespace: A<br />');
        }
    }
}

namespace B\A
{
    class A
    {
        public function __construct()
        {
            echo('namespace: B\\A<br />');
        }
    }
}

namespace B
{
    class B
    {
        public function __construct()
        {
            new \A\A(); // namespace: A
            new A\A(); // namespace: B\A
        }
    }
    new B();
}

使用前导反斜杠,您将获得绝对路径,没有它,您将获得相对路径。

于 2011-02-08T08:41:21.743 回答
-3

别说我们有

namespace MyNamespace
use Exception;
use \Exception;

然后第一次使用实际上导入类 MyNamespace\Exception 而第二个只是主类 \Exception

所以你可以有类似的东西

namespace MyNamespace;
class Exception extends \Exception{ }

然后我可以

throw new \Exception('Exception from global namespace');
throw new \MyNamespace\Exception('Exception from MyNamespace');
于 2011-01-31T10:08:04.883 回答