当前位置:  开发笔记 > 编程语言 > 正文

PHP中静态成员的继承

如何解决《PHP中静态成员的继承》经验,为你挑选了3个好方法。

在PHP中,如果在父类中定义了静态属性,则不能在子类中重写它.但我想知道是否有任何解决方法.

我正在尝试为其他人(有点笨重)的函数编写一个包装器.有问题的函数可以应用于许多不同的数据类型,但每个都需要不同的标志和选项.但99%的时间,每种类型的默认值就足够了.

如果可以通过继承完成,而不必每次都编写新函数,那将是很好的.例如:

class Foo {
    public static $default = 'DEFAULT';

    public static function doSomething ($param = FALSE ) {
        $param = ($param === FALSE) ? self::$default : $param;
        return $param;
    }
}

class Bar extends Foo {
    public static $default = 'NEW DEFAULT FOR CHILD CLASS';
}

echo Foo::doSomething() . "\n"; 
// echoes 'DEFAULT'

echo Bar::doSomething() . "\n"; 
// echoes 'DEFAULT' not 'NEW DEFAULT FOR CHILD CLASS' 
// because it references $default in the parent class :(

Attila Wind.. 33

实际上我认为这不是真的:你可以改变静态的特性(你需要> = 5.3 PHP).但是在为这个静态属性重新启动时你必须要小心(这是原始代码中的错误)

你需要使用static :: $ myStaticProperty而不是使用self :: $ myStaticProperty

self ::将refrence to current class so如果你在一个继承的静态方法中,这将引用该方法定义的那个类的静态属性!使用引用关键字static ::将像$ this一样 - 当您使用实例方法/ propeties时.

doSomething()是示例中类Bar中的继承静态方法.由于你使用self :: there,它将引用类Foo的static属性.这就是你没有看到任何区别的原因... 尝试将self ::更改为static ::!

这是一个代码示例 - 我自己用它来测试这些东西.我们有静态属性/方法继承,覆盖和值更改 - 运行它,你会看到结果!

class A {

    // a static property - we will test override with it
    protected static $var = 'class A var - override';
    // a static property - we will test value overwrite with it
    protected static $var2 = 'class A var2 - value overwrite';


    public static function myStaticOverridePropertyTest() {
        return static::$var;
    }
    public static function myStaticValueOverwritePropertyTest() {
        return static::$var2;
    }

    /**
     * This method is defined only here - class B will inherit this one!
     * We use it to test the difference btw self:: and static::
     * 
     * @return string
     */
    public static function myStaticMethodTest() {
        //return self::getValue();
        return static::getValue();
    }

    /**
     * This method will be overwritten in class B
     * @return string
     */
    protected static function getValue() {
        return 'value from class A';
    }
}


class B extends A {

    // we override this inherited static property
    protected static $var = 'class B var - override';

    /**
     * This method is overwritten from class A
     * @return string
     */
    protected static function getValue() {
        return 'value from class B';
    }

    /**
     * We modify the value of the inherited $var2 static property
     */
    public static function modStaticProperty() {
        self::$var2 = 'class B - altered value! - value overwrite';
    }
}

echo ("-- testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

echo ("-- now testing class B:\n");
echo (B::myStaticOverridePropertyTest(). "\n");
echo (B::myStaticValueOverwritePropertyTest(). "\n");
echo ("  now invoking B::modStaticProperty()     .\n");
B::modStaticProperty();
echo (B::myStaticValueOverwritePropertyTest(). "\n");

echo ("-- now re-testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

这将输出:

- 测试类A:
类A var - 重写
类A var2 - 值覆盖
来自类A的值
- 现在测试类B:
类B var - 重写
类A var2 - 值覆盖
现在调用B :: modStaticProperty( )......
B级 - 改变价值!- 值覆盖
- 现在重新测试类A:
类A var - 覆盖
类B - 改变了值!-
来自A类的值覆盖

我们在这里,您可以看到覆盖和仅覆盖静态属性之间的差异...查看我用粗体标记的输出行!当我们调用类B的modStaticProperty()时,它也改变了类A中的静态变量的值.由于该静态属性是继承的并且未被覆盖!想一想......



1> Attila Wind..:

实际上我认为这不是真的:你可以改变静态的特性(你需要> = 5.3 PHP).但是在为这个静态属性重新启动时你必须要小心(这是原始代码中的错误)

你需要使用static :: $ myStaticProperty而不是使用self :: $ myStaticProperty

self ::将refrence to current class so如果你在一个继承的静态方法中,这将引用该方法定义的那个类的静态属性!使用引用关键字static ::将像$ this一样 - 当您使用实例方法/ propeties时.

doSomething()是示例中类Bar中的继承静态方法.由于你使用self :: there,它将引用类Foo的static属性.这就是你没有看到任何区别的原因... 尝试将self ::更改为static ::!

这是一个代码示例 - 我自己用它来测试这些东西.我们有静态属性/方法继承,覆盖和值更改 - 运行它,你会看到结果!

class A {

    // a static property - we will test override with it
    protected static $var = 'class A var - override';
    // a static property - we will test value overwrite with it
    protected static $var2 = 'class A var2 - value overwrite';


    public static function myStaticOverridePropertyTest() {
        return static::$var;
    }
    public static function myStaticValueOverwritePropertyTest() {
        return static::$var2;
    }

    /**
     * This method is defined only here - class B will inherit this one!
     * We use it to test the difference btw self:: and static::
     * 
     * @return string
     */
    public static function myStaticMethodTest() {
        //return self::getValue();
        return static::getValue();
    }

    /**
     * This method will be overwritten in class B
     * @return string
     */
    protected static function getValue() {
        return 'value from class A';
    }
}


class B extends A {

    // we override this inherited static property
    protected static $var = 'class B var - override';

    /**
     * This method is overwritten from class A
     * @return string
     */
    protected static function getValue() {
        return 'value from class B';
    }

    /**
     * We modify the value of the inherited $var2 static property
     */
    public static function modStaticProperty() {
        self::$var2 = 'class B - altered value! - value overwrite';
    }
}

echo ("-- testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

echo ("-- now testing class B:\n");
echo (B::myStaticOverridePropertyTest(). "\n");
echo (B::myStaticValueOverwritePropertyTest(). "\n");
echo ("  now invoking B::modStaticProperty()     .\n");
B::modStaticProperty();
echo (B::myStaticValueOverwritePropertyTest(). "\n");

echo ("-- now re-testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

这将输出:

- 测试类A:
类A var - 重写
类A var2 - 值覆盖
来自类A的值
- 现在测试类B:
类B var - 重写
类A var2 - 值覆盖
现在调用B :: modStaticProperty( )......
B级 - 改变价值!- 值覆盖
- 现在重新测试类A:
类A var - 覆盖
类B - 改变了值!-
来自A类的值覆盖

我们在这里,您可以看到覆盖和仅覆盖静态属性之间的差异...查看我用粗体标记的输出行!当我们调用类B的modStaticProperty()时,它也改变了类A中的静态变量的值.由于该静态属性是继承的并且未被覆盖!想一想......



2> Paul Dixon..:

即将推出的PHP 5.3.0版本包括后期静态绑定,这可能有所帮助.使用此功能,您可以在静态方法中使用静态变量,并让后期静态绑定负责查找"正确"方法.

class Foo {
    public static function getDefault() {
        static $default = 'DEFAULT';
        return $default;
    }
    public static function doSomething ($param) {
        $default=static::getDefault(); // here is the late static binding
        $param = ($param === FALSE) ? $default : $param;
        return $param;

    }
}

class Bar extends Foo {
     public static function getDefault() {
        static $default = 'NEW DEFAULT FOR CHILD CLASS';
        return $default;
    }
}



3> Allain Lalon..:

使用静态作为全局变量(在这种情况下是函数)的经典示例无论语言如何都是一个坏主意.

最强大的方法是创建抽象基类"Action"类的多个实现子类.

然后尝试去除实例化类的实例只是为了调用它的方法的一些烦恼,你可以将它包装在某种类型的工厂中.

例如:

abstract class AbstractAction {
  public abstract function do();
}

class FooAction extends AbstractAction {
  public function do() {
    echo "Do Foo Action";
  }
}

class BarAction extends AbstractAction {
  public function do() {
    echo "Do Bar Action";
  }
}

然后创建一个工厂来"辅助"实例化该功能

class ActionFactory {
  public static function get($action_name) {
    //... return AbstractAction instance here
  }  
}

然后用它作为:

ActionFactory::get('foo')->do();

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有