一个 php 的“可变类名”疑问

2015-01-05 12:28:51 +08:00
 kmvan
<?php
class_a::init();
class class_a{
    public static $other_class_name = 'class_b';
    public static function init(){
        $other_class_name = self::$other_class_name; //一定要这样赋值才能 work 吗?
        $other_class_name::init(); //不能直接写 self::$other_class_name::init(),郁闷
       //有办法不用去赋值,直接写静态变量作为类名来调用 class_b 的方法吗?
    }
}
class class_b{
    public static function init(){
        echo 'i am class_b';
    }
}
class class_c{
    public static function init(){
        echo 'i am class_c';
    }
}
4079 次点击
所在节点    PHP
19 条回复
haiyang416
2015-01-05 12:39:03 +08:00
call_user_func(array(self::$other_class_name, 'init'));

只想到这个,写两行有什么不好么?
fising
2015-01-05 12:46:32 +08:00
self::$other_class_name::init()

明显不对啊。

self::$other_class_name 得到的是字符串 'class_b'

你能对字符串调用静态方法init?
hitsmaxft
2015-01-05 12:49:54 +08:00
这些属于php语法分析的bug,用 call user func 绕开
raincious
2015-01-05 12:51:51 +08:00
PHP现在T_PAAMAYIM_NEKUDOTAYIM的解析有点“未完待续”。5.3的时候连$variable::method();的语法都无法解析。

到5.6还是不能将::串联起来,必须在函数/方法体内本地化一个变量才可以。哪怕你制造一个静态方法:

function static class getClass() { return static::$other_class_name; }

然后 static::getClass()::init(); 都不行。

所以目前只能用一楼的方法,只是效率比较低。
kmvan
2015-01-05 13:10:38 +08:00
@raincious 所以目前只能用一楼的方法,只是效率比较低。
其实还有一种写法,就是用 eval,不过效率恐怕比一楼的还要低。
我还想问一下,$other_class_name::init(); 这种写法,应该不是叫可变变量吧,有专用的名词吗?可变变量是 $$name 这样子的。
kmvan
2015-01-05 13:11:34 +08:00
@haiyang416 只想到这个,写两行有什么不好么?
对于病患来说,写多半行都觉得整个人不好了。
kmvan
2015-01-05 13:14:35 +08:00
@haiyang416 call_user_func(array(self::$other_class_name, 'init'));
这个估计不行吧,因为他是静态方法,不会报错吗?
haiyang416
2015-01-05 13:21:21 +08:00
@kmvan 不要说你认为不行。你应该先上代码实验或者翻阅对应的手册。
kmvan
2015-01-05 13:40:07 +08:00
@haiyang416 不要说你认为不行。你应该先上代码实验或者翻阅对应的手册。
类型不标准,虽然不是error错误,但也报提示: Strict standards: call_user_func() expects parameter 1 to be a valid callback, non-static method class_b::init() should not be called statically
picasso250
2015-01-05 13:43:18 +08:00
唯一的办法是给PHP提patch

@raincious 手工感谢
raincious
2015-01-05 14:13:18 +08:00
@kmvan

我这里改成这样:
https://gist.github.com/anonymous/5e7191f4fd142249d06b

运行没有问题。你可能错在别的地方了,比如init没声明static?

call_user_func这个函数可以看作支持某种程度上的“多态”。

比如(如果有错请指正):

call_user_func('FunctionName'); // 这样是调用函数(静态的)

call_user_func(array('ClassName', 'MethodName')); // 这样就是调用静态方法。

$instance = new class();
call_user_func(array($instance, 'MethodName')); // 这样就是调用实例方法。
haiyang416
2015-01-05 14:14:36 +08:00
laoyuan
2015-01-05 14:55:37 +08:00
好问题,正在看《PHP核心技术与最佳实践》里讲多态的一节
LuckyHJH
2015-01-05 16:49:28 +08:00
我遇到的问题是,new $class_name() 就会报错,PHP5.3.3,不知道是否同一个问题
haiyang416
2015-01-05 17:03:34 +08:00
LuckyHJH
2015-01-05 17:14:54 +08:00
感谢15楼,另外话说为什么每次打开这个页面,都总在11楼那里卡一卡 - -
sumhat
2015-01-05 18:50:27 +08:00
我来歪个楼。不太懂 PHP,但是为什么一定要用静态方法,不能直接扔一个实例进去么?
ichou
2015-01-05 22:33:06 +08:00
为什么我是第一次见这种用法 。。。
大大们可以解释一下使用场景么?
kmvan
2015-01-05 22:44:52 +08:00
@ichou 为什么我是第一次见这种用法 。。。
不是吧?php可变变量很常见,很实用,但它可变的不够完全,郁闷啊…不过这点小瘕疵,不影响他是世界上最好的语言

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/159331

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX