如何防止继承类中的静态变量共享?

时间:2016-11-12 23:02:16

标签: php inheritance static

考虑Model.php

class Model {
    protected static $class_name;
    protected static $table_name;

    protected $id;

    public static function initialize() {
        static::$class_name = get_called_class();
        static::$table_name = strtolower(static::$class_name).'s';
    }
}

及其子女User.phpProduct.php

class User extends Model {
    protected $username;
    protected $password;
}
User::initialize();

class Product extends Model {
    protected $name;
    protected $price;
}
Product::initialize();

由于每个UserProduct都具有相同的$class_name$table_name,因此将其设为static是有意义的。在子模型上调用initialize()方法时会分配实际值(例如User::initialize();Product::initialize();)。

问题

我希望最终得到以下结论:

User    -> $class_name -> 'User',    $table_name -> 'users'
Product -> $class_name -> 'Product', $table_name -> 'products'

但我得到以下内容:

User    -> $class_name -> 'User',    $table_name -> 'users'
Product -> $class_name -> 'User',    $table_name -> 'users'

考虑到我使用static::的后期静态绑定,这怎么可能?如何解决这个问题?我的目标是让UserProduct拥有独立的class_nametable_name,但仍保留两个变量 { {1}} ,希望无需在每个模型上重新声明,无论是staticUser还是其他任何内容!

2 个答案:

答案 0 :(得分:0)

调用Product::initialize时,Model::$class_name设置为"Product"Model::$table_name设置为"products"。调用User::initialize后,Model::$class_nameModel::$table_name将被"User""users"覆盖。

初始化中的static只会产生差异,如果这些属性是在子类中定义的。

你自己回答问题的第二部分,要么重新声明它们,要么使它们成为非静态的。

修改

您可以将地图与访问器结合使用来伪造子类本地继承的静态属性(我希望我只是这样做了)。

class Foo {
        private static $class_names = [];
        private static $table_names = [];

        public static function getClassName() {
                return self::$class_names[static::class];
        }

        public static function getTableName() {
                return self::$table_names[static::class];
        }

        public static function initialize() {
                self::$class_names[static::class] = static::class;
                self::$table_names[static::class] = strtolower(static::class).'s';
        }
}

class Bar extends Foo {
}
Bar::initialize();

class Baz extends Foo {
}
Baz::initialize();

echo Bar::getTableName() . " " . Bar::getClassName() . "\n";
echo Baz::getTableName() . " " . Baz::getClassName() . "\n";

在PHP 7中,声明动态静态属性确实不起作用。

答案 1 :(得分:-1)

阅读接受的答案后,我有了使用classCallerContainer的解决方法。

class ParentClass{

    protected static $container = [];


    protected static function setIndependentProperty($string){
        //# stored the the caller class as the bank
        static::$container[get_called_class()] = $string;
    }
    protected static function getIndependentProperty(){

        //# collect the value in container base on the caller class
        return static::$container[get_called_class()] ?? "";
    }


}