php面向对象——static后期静态绑定

1:static访问符

  • 在类中使用static有两种主要用途、定义静态成员和定义静态方法。静态成员只保留一个变量的值,这个值对所有实例都是有效的
  • 类的方法是static的,他所访问的属性也必须是static的

2:static后期静态绑定

什么是静态绑定?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class U {
 
}
class u1 extends U {
    public static function create() {
        return new u1();
    }
 
}
class u2 extends U {
    public static function create(){
        return new u2();
    }
}

这段代码正常工作是没问题,但大量重复的代码会很烦人

我不想在每个子类中添加create方法,如果把create方法放在超类U中,代码可能是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class U
{
    public static function create()
    {
       //return new self();  //self 会报错,self对该类所起的作用与$this对对象所起的作用并不完全相同。self指的不是调用上下文,他指的是解析上下文,<br>//因此如果运行上面的列子,将会得到<br>//Fatal error: Cannot instantiate abstract class U in D:wampwwwtestoopstatic.php on line 21<br>//因此self被解析为定义create的U,而不是解析为调用self的u1类。<br><br>    //static不仅可以用于实例化,和self,parent一样还可以作为静态方法的调用标识符,甚至是从非静态上下文中调用<br>    return new static();
    }
 
}
 
class u1 extends U{
 
}
 
class u2 extends U{
 
}
$res = u1::create();
var_dump($res);

 static不仅可以用于实例化,和self,parent一样还可以作为静态方法的调用标识符,甚至是从非静态上下文中调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
abstract class U
{
    private $group;
    public function __construct()
    {
        $this->group = static::getGroup();
    }
 
    public static function create()
    {
        return new static();
    }
 
    static function getGroup()
    {
        return 'default';
    }
 
}
 
class u1 extends U
{
     
}
 
class u2 extends U
{
    static function getGroup()
    {
        return 'u2';
    }
 
}
 
class u3 extends u2
{
     
}
 
print_r(u1::create());

u1 Object ( [group:U:private] => default )

u3 Object ( [group:U:private] => u2 )

 

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A {
    public static function foo() {
        static::who();
    }
  
    public static function who() {
        echo __CLASS__."\n";
    }
}
class extends A {
    public static function test() {
        A::foo();  //如果换成static,则向后绑定,如果是A,则最底层的类是A
        parent::foo();
        self::foo();
    }
  
    public static function who() {
        echo __CLASS__."\n";
    }
}
class extends B {
    public static function who() {
        echo __CLASS__."\n";
    }
}
C::test();

 输出:A C C

 

3: 属性不能被定义为 final,只有类和方法才能被定义为 final。

如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。

 

4:对象复制

 

5:对象继承

parent能调用父类的非静态方法吗?

self能调用父类的静态方法吗?

php支持继承多个类吗?

父类调用之类怎么调用?

子类调用父类怎么调用?

$this能调用静态方法吗?

同样的类名和接口名可以放在一起吗?

子类的同名访问符可以小于父类的吗?

php支持多态吗?

 

1> parent能调用父类的非静态方法吗?

parent既能调用父类的静态方法,也可以调用父类的非静态方法; parent不可以调用子类,只能调用父类的; parent关键字解决的就是调用父类的方法;

  self无论父类还是子类的静态方法,非静态方法都可以调用(对所有的无限制)

  parent常用于构造函数中调用父类的构造函数

2>self能调用父类的静态方法吗?

3>父类调用之类怎么调用?

静态方法,属性用static,$this(虽然可以访问,但是不建议这样来做)

非静态方法,属性用$this, static

4>子类调用父类怎么调用?

用$this, parent, static

5>如果子类和父类有相同的方法,但是父类的是private方法,父类调用的时候调用的是哪个方法?

父类调用的是他自己的,而不是子类的。对于私有方法(private)修饰的方法,$this找的方法是先找本类里的。 protect,public都可以被覆盖。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Child
{
    public function __construct()
    {
        $this->setInstance($this);
    }
 
    private function setInstance($instance)
    {
        echo 'Child';
    }
}
 
class ChildChild extends Child
{
 
    public function __construct()
    {
        parent::__construct();
    }
 
    public  function setInstance($instance)
    {
        echo 'ChildChild';
    }
}
$obj new ChildChild();

 

 输出:Child 【因为他是private,$this调用的时候调用它】

如果改成public,或protected,则返回ChildChild

 

 

5>子类的同名访问符可以小于父类的吗?

子类的修饰符号不能小于父类的

 

3>同样的类名和接口名不能放在一起。

 

同样的类名和接口名可以放在一起吗?

Class and Interface share SAME namespace!

class k{}
interface k {}    // Fatal error: Cannot redeclare class k

 

6:$this, self,parent,static

1> $this访问变量不加$, self:: 访问需要加

$this->name;   self::$sName;

2>

$this能访问静态变量,静态方法,但是不能访问常量;

而self, parent, static 不能访问非静态变量,只能访问静态的变量或常量; 但是self,parent,static都能访问非静态方法。self也能访问父类的非静态方法和静态方法。

 

php支持多态吗?

多态:多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数。

PHP只支持覆盖(override),而不支持重载(overload)。

PHP5 中重载可以通过 __get, __set, and __call 几个特殊方法来进行。当 Zend 引擎试图访问一个成员并没有找到时,PHP将会调用这些方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function __call($method$p)
{
    print("Invoking $method()<br>\n");
    if($method == 'display')
    {
        if(is_object($p[0]))
            $this->displayObject($p[0]);
        else
            if(is_array($p[0]))
                $this->displayArray($p[0]);
            else
                $this->displayScalar($p[0]);
    }
}

 __CLASS__, __FUNCTION__ 在哪个类里,就显示哪个,而不管$this是谁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Child
{
    public function __construct()
    {
        static::setInstance($this);
    }
}
 
class ChildChild extends Child
{
 
    public function __construct()
    {
        parent::__construct();
    }
 
    public  function setInstance($instance)
    {
        echo __CLASS__ ' || ' __FUNCTION__;
        echo 'childChild';
    }
}
$obj new ChildChild();

 返回: ChildChild || setInstance childChild

 

static访问符号的顺序为: 从后往前

子类 > 本类 > 父类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Base
{
    protected static $instances;
 
    public function setInstance($instance)
    {
        echo 'Base';
    }
}
class Child extends Base
{
    public function __construct()
    {
        static::setInstance($this);
    }
 
    public function setInstance($instance)
    {
        echo 'Child';
    }
}
 
class ChildChild extends Child
{
    public function setInstance($instance)
    {
        echo 'ChildChild';
    }
}
$obj new ChildChild();

 输出: ChildChild

 

总结:

访问静态方法,静态属性:static,parent,self, $this

访问常量: self, parent, static

访问非静态方法,属性: $this, static, parent, self

子类访问父类: $this, parent, self, static

父类访问子类: static, $this

 联系我们

  • 邮箱:admin@admincms.top
  • 官方博客:blog.admincms.top
  • 官方微信公众号:huayuejishu
扫描二维码关注Joker.Liu微信公众号
TOP博客官方微信公众号二维码