【问题标题】:PHP - Setting inherited static property will also set it in other classes inheriting itPHP - 设置继承的静态属性也会在其他继承它的类中设置它
【发布时间】:2012-06-01 09:33:18
【问题描述】:

我有一个代表 html 元素的类层次结构。其中一些可能与某些浏览器版本不兼容。例如,HTML5 画布与版本 9 之前的 Internet Explorer 不兼容。

对于每种类型的元素,我希望能够知道调用浏览器是否支持它们。

abstract class AbstractView // Base class, doesn't represent anything.
{
    // ...

    // By default, an element will be considered compatible with any version of ny browser.
    protected static $FirstCompatibleVersions = array(
        'Firefox' => 0,
        'Chrome' => 0,
        'Internet Explorer' => 0);

    protected static function SetFirstCompatibleVersion($browser, $version)
    {
        static::$FirstCompatibleVersions[$browser] = $version;
    }

    protected static function IsSupportedByBrowser()
    {
        $browser = // ... Assumed to be the calling browser name.
        $version = // ... Assumed to be the calling browser version.
        return static::$FirstCompatibleVersions[$browser] <= $version;
    }
}

class CanvasView extends AbstractView // Displays a canvas. Not compatible with IE < 9.
{
    // ...
}

CanvasView::SetFirstCompatibleVersion('Internet Explorer', 9);

class FormView extends AbstractView // Displays a form. Assumed compatible with anything.
{
    // ...
}

// Nothing to do form FormView.

echo FormView::IsSupportedByBrowser(); // Should print 1 (true) (on firefox 12) but does not.

我的问题是,当我执行时:

CanvasView::SetFirstCompatibleVersion('Internet Explorer', 9);

这不仅会设置 CanvasView::$FirstCompatibleVersion['Internet Explorer'],还会为所有其他类设置这个值,就像这个数组对所有类一样,使我的所有元素与IE

我能做些什么来防止这种情况发生?

感谢您抽出宝贵时间阅读。

-病毒

【问题讨论】:

  • 忘了提醒,如果我在每个子类中重新声明 $FirstCompatibleVersions 数组,它工作正常。

标签: php static inheritance


【解决方案1】:

在静态方法中,您可以使用get_called_class() (PHP 5.3+) 来了解正在调用哪个类。

FormView::SetFirstCompatibleVersion()

get_called_class() 将返回 'FormView'。这就是您可以区分子类的方法。

【讨论】:

  • 我试图:“$class= get_call_class(); ... $class::...”而不是“static::...”,但它似乎具有相同的行为。还是谢谢
  • @Virus721 我认为他建议在 FirstCompatibleVersions 数组中存储类的名称:static::$FirstCompatibleVersions[get_called_class()][$browser] = $version;。然后你可以使用return static::$FirstCompatibleVersions[get_called_class()][$browser] &lt;= $version;。您还需要为每个类分配一个默认值。
  • @virus721 不同之处在于,使用 get_call_class() 您可以获得一个字符串,您可以使用它来区分子类。基本上是 meze 解释的。
  • 它似乎工作,非常感谢大家。虽然不能“继承”。如果我说 CanvasView 与 IE
  • @virus721 如果这有帮助并且您的代表已达到 15 位,请考虑支持 :)
【解决方案2】:

你无法阻止这一点。 AbstractView 的所有子级共享类静态变量。您可以改用对象或在每个类的静态变量中设置它们的兼容性,而不是使用 SetFirstCompatibleVersion。

【讨论】:

  • 这就是我一直在考虑的,但由于我有很多元素(超过 100 个),我必须在每个元素上添加一个受保护的静态数组。如果有人创建了一个新元素,他可能会忘记创建这个数组,因此对象将共享父类数组(如果我理解得很好的话)。谢谢你的回答!
  • @Virus721 你仍然需要调用 SetFirstCompatibleVersion 超过 100 次,不是吗?也有人会忘记叫它……
  • 不完全是,我只想在元素与调用浏览器存在兼容性问题时才调用它。大多数 html 4 元素不必使用此功能,但某些 html 5 元素必须在某些浏览器中使用。但是我仍然需要给我的元素自己的数组,否则它将使用父类的数组,对吗?
  • @Virus721 我说的是class CanvasView extends AbstractView { protected function getFirstCompatibleVersions() { return array('Internet Explorer' =&gt; 9); } }
  • 你的意思是我应该在我的基类中放置一个 getFirstCompatibleVersion 静态函数(它会像你一样返回一个数组),并在有兼容性问题的类中覆盖它?
猜你喜欢
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多