当前位置: 首页 > 后端技术 > PHP

PHP静态方法和属性,延迟静态绑定

时间:2023-03-30 05:02:19 PHP

静态方法和属性静态方法是具有类作用域的函数。静态方法不能访问此类中的普通属性,因为那些属性属于一个对象,但是可以访问静态属性。如果修改了静态属性,则该类的所有实例都可以访问新值。因为静态元素是通过类而不是实例来访问的,所以访问静态元素时不再需要引用对象的变量,而是用::来连接类名和属性或者类名和方法。类StaicExample{静态公共$aNum=0;staticpublicfunctionsayHello(){打印“你好”;}}printStaicExample::$aNum;StaicExample::sayHello();子类可以使用parent关键字访问父类,而无需使用其类名。要从当前类(而非子类)中访问静态方法或属性,可以使用self关键字。self指向当前类,就像伪变量$this指向当前对象一样。因此,在StaticExample类之外,您可以使用它的类名来访问属性$aNum:StaicExample::$aNum;在StaticExample类中,您可以使用self关键字:classStaticExample{staticpublic$aNum=0;staticpublicfunctionsayHello(){self::$aNum++;打印"你好(".self::$aNum.")\n";}}只有使用parent关键字调用方法,才能静态调用非静态方法(use::)。除非你正在访问一个重写的方法,否则你只能使用::来访问显式声明为静态的方法或属性。有时看到使用静态语法来引用方法或属性,可能并不意味着该方法或属性一定是静态的,而是属于特定的类。根据定义,不能在对象中调用静态方法。因此,静态方法和属性也称为类变量和属性,静态方法中不能使用伪变量$this。为什么要使用静态方法或属性?在代码的任何地方都可用(假设您有权访问该类)。也就是说,你不需要在对象之间传递类的实例,也不需要将实例存储在全局变量中来访问类中的方法。类的每个实例都可以访问类中定义的静态属性,因此可以使用静态属性来设置类的所有对象都可以使用的值。可以在没有实例对象的情况下访问静态属性或方法,因此您不必为了获得一个简单的功能而实例化一个对象。延迟静态绑定:static关键字静态方法可以用作工厂方法,工厂方法是一种生成包含类实例的方法。先看下面重复的代码:abstractclassDomainObject{}classUserextendsDomainObject{publicstaticfunctioncreate(){returnnewUser();}}classDocumentextendsDomainObject{publicstaticfunctioncreate(){returnnewDocument();}}想必大家都不想为每一个DomainObject子类都创建类似于上面代码的标准代码。如果将create()放在超类中会怎样?抽象类DomainObject{publicstaticfunctioncreate(){returnnewself();}}classUserextendsDomainObject{}classDocumentextendsDomainObject{}Document::create();这次看起来简洁多了。现在将公共代码放在一个地方,并使用self作为类的引用。事实上,self对类的作用与$this对对象的作用不同。self指的不是调用上下文,而是解析上下文。因此,刚才运行上面的代码会得到:PHPFatalerror:CannotinstantiateabstractclassDomainObjectin...因此self被解析为定义create()的DomainObject,而不是调用self的Document类。在PHP5.3之前,这方面有严格的限制,导致出现了许多笨拙的解决方案。PHP5.3引入了延迟静态绑定的概念。此功能最明显的标志是新关键字static。static类似于self,但它指的是被调用类而不是包含类。在这种情况下,这意味着调用Document::create()将生成一个新的Document对象,而不是尝试实例化DomainObject对象。因此,继承关系现在用于静态上下文中。抽象类DomainObject{publicstaticfunctioncreate(){returnnewstatic();}}classUserextendsDomainObject{}classDocumentextendsDomainObject{}print_r(Document::create());//DocumentObject{}static关键字不只是为了实例化。与self和parent一样,static也可以用作静态方法调用的标识符,即使是来自非静态上下文。如果要为DomainObject引入组(group)的概念。默认情况下,所有类都属于默认类别,但可以覆盖继承层次结构的某些分支的类别。抽象类DomainObject{private$group;公共函数__construct(){$this->group=static::getGroup();}publicstaticfunctioncreate(){returnnewstatic();}staticfunctiongetGroup(){返回“默认值”;}}classUserextendsDomainObject{}classDocumentextendsDomainObject{staticfunctiongetGroup(){return"document";}}类SpreadSheet扩展文档{}print_r(User::create());print_r(SpreadSheet::create());在DomainObject类中定义构造函数。此构造函数使用static关键字调用静态方法getGroup()。DomainObject提供了默认实现,但Document覆盖了它。创建的新SpreadSheet类扩展了Document类。下面是打印结果:UserObject([group:DomainObject:private]=>default)SpreadSheetObject([group:DomainObject:private]=>document)最后根据自己的理解写一个例子:model=static::getModel();//延迟绑定}publicfunction__get($name){return$this->{'get'.ucfirst($name)}();}publicstaticfunctiongetModel(){return'Model';}publicfunctiongetModelName(){return$this->model;}publicfunction__toString(){return$this->modelName;}}classUserextendsModel{publicstaticfunctiongetModel(){return'User';}}classBookextendsModel{publicstaticfunctiongetModel(){return'Book';}}$model=新模型;$user=新用户;$book=新书;echo$model。PHP_EOL;//模型回显$user.PHP_EOL;//用户回显$book.PHP_EOL;//Book为Model类的构造函数中的s在tatic::getModel()被self::getModel()修改后:echo$model。PHP_EOL;//模型回显$user.PHP_EOL;//Modelecho$book.PHP_EOL;