一个问题证明中国的程序员很烂

放牛娃1988 发布于 2012/09/22 22:57
阅读 2K+
收藏 2
OK,本来我想写一篇文章,详细介绍一个PHP的语法从诞生到不断演变,最后无法自圆其说的过程。这件事情非常有趣,因为它探讨了PHP随性的语法究竟有怎样的害处,以及如何避免这种害处。但是我没兴趣写,因为我在论坛刚刚抛出这个 问题,就发现90%的人根本看不懂我那短短的10行代码就开始和我辩论。只有 @朱亚杰 @Troy @Corz @32789mm3600 等少数几个人能够知道这是个什么问题。更多的人,要么就是凑热闹,要么就根本不懂我说的是什么。

好吧,我再整理一下这个问题,详细跟你们说清楚这个语法现象的来龙去脉(没信心看懂的直接绕过以下内容开始狂念三字经)

------------------------------------------------技术分割线

PHP中,一般静态方法是用ClassName::MethodName来调用,非静态方法采用ObjectName->MethodName来调用,在继承层次上调用祖先类的特定方法,则不论是静态还是非静态,一律::调用。但是PHP对语法的包容性很强,事实上,这两种调用方法可以互换,而PHP不会出错,最多会给出一个Notice来提示。为何能够如此包容,根本原因在于,对于一个特定的类的特定方法,究竟是静态还是非静态,是很明确定义的,它无需根据调用符号来确定,而只需根据类的定义来确定。比如Bird类有一个非静态方法叫fly(),那么无论你是用::来调用,还是用->来调用,它都是非静态方法,没有歧义,所以PHP采取了容忍的策略。

但是后来PHP又引入了魔术方法__call和__callStatic,这两个方法分别用于调用不存在的非静态方法和静态方法设计的,就产生了冲突。举个例子吧:
class A
{
	public function __call($method, $args)
	{
		echo 'NON-STATIC';
	}
	
	public static function __callStatic($method, $args)
	{
		echo 'STATIC';
	}
}

class B extends A
{
	public function test()
	{
		A::call();
		parent::call();
	}
}
$b = new B();
$b->test();

前面我们说过了,这个parent::call()调用的方法究竟是静态还是非静态,得取决于类A的call方法是静态还是非静态,可是类A没有这个方法,那么它到底算静态还是非静态呢?PHP在5.3.3认为它是静态的,可是有人说是BUG,好吧,改成非静态,可是又有人说是BUG,要求改回来,为什么呢?因为这两个在语法上都是合理的,可是它们又是完全冲突的,所以从语法角度上来说,产生了严重的不自洽。现在,只能强制认定,这种调用取决于调用的方法是静态还是非静态。

这种强制规定完全是乱来,调用的方法是静态的,只能调用祖先类的静态方法,这个是没问题的,可是调用的方法是非静态,凭什么被调用的就只能是非静态?子类的非静态方法调用父类的静态方法不是非常常见的需求吗?那如果我想要魔术方法调用父类的静态方法怎么办?可见这个规定完全是因为语法不能自圆其说而采取的强制性规定。好比在if(a < b)当中,规定当a=3,b=1是为true,其他的按照正常的大小进行比较。这种规定当然可行,但是你不觉得有点怪异吗?

PHP的语法随意性,给程序员带来便利的同时,也给很多语法问题带来了困惑。从语言的角度来说,无论是语法设计的优雅性,还是由于其高度容忍性导致程序员的代码混乱,都是一个不容忽视的问题。

------------------------------------------------技术分割线

再次声明:

1)这个不是什么所谓的BUG,BUG指的是明显错误的地方,可以改正;而这个问题不管怎么改,都有人认为是错的,有人认为是对的,因为它没法自圆其说了。

2)看不懂问题的人,可以回帖打酱油,但是请不要一本正经地和我辩论,我真心觉得恶心

3)中国的程序员很烂,指的是总体水平很烂,不针对个人,主要针对的是那些看不懂问题,还一个劲地讨论,跟他解释之后,他还是不懂,反而觉得自己高明的弱智分子,你们真的很烂、很烂、很烂,You suck!@小郭一号

4)最后强调一遍,单根继承的意义是“一个子类只允许一个父类”,C++当然允许子类只有一个父类,但是“允许”和“只允许”完全是两回事,不要说什么C++是单根继承这种可笑的话来,连这个逻辑都分不清的人,也很烂@小耶果

大家都很烂,一起烂吧,烂熟透了,踩踩就成肥料了,大家一起来踩吧

加载中
0
cut
cut
这种问题,C++,JAVA,C#都有,不就是看上去分不清是类对象函数还是类静态函数么,硬说的自己好像很牛逼的样子,对于语法来说一点问题都没,但写这样程序的人实在不想多加评论,应多从自己身上找找问题。在傻逼眼里的世界都是傻逼。
放牛娃1988
放牛娃1988
我这篇文章说的烂程序员就是上一个帖子里,看不懂代码却高谈阔论的人。设为最佳答案,让大家看看。
放牛娃1988
放牛娃1988
不打自招,这是一个看不懂问题却高谈阔论的烂程序员,You suck,你是中国烂程序员的典型代表。
1
朱__朱
朱__朱

是的,这不是php开发者的编码失误造成,不是bug,是语法实现问题导致的,类似的问题还有一些。一方面,对->和::没有在语法分析阶段进行严格区分,另一方面又搞了__call和__callStatic对魔术调用进行严格区分,导致parent::触发魔术方法时存在选择问题,不管选哪个,都肯定会有一边认为是对的,另一边人认为是错的。

不过php的速度和灵活,也恰恰得意于dirty and quick的实现方式......

大部分类似的问题,都是在正常开发中几乎不会遇到的情形。而且,有点经验的程序员即使遇到了,也可以简单地绕过不算什么难事。

像parent::触发魔术方法这个问题,绕过去还是比较简单的

get_parent_class(__CLASS__)::可以精确触发静态方法

如果parent::需要严格触发非静态方法,可以把在__calStatic里面用if创建一个分支,把__call里面的代码完整复制到分支中,并用$that替换掉$this。然后从子类用这样的方式调用:parent::test($param,...,$this,$check)

在__callStatic里面检测传入的最后一个参数是否是$check变量,检测到$check,就明白访问来路是parent,然后进入为它准备的分支,把传入的倒数第二个参数(即$this)赋值给$that变量,这样php触发的是__callStatic,执行结果与__call也会完全一致。如果没有检测到$check,说明这是一个正常的classname::调用,执行常规代码即可。

放牛娃1988
放牛娃1988
yes, very right!
0
宏哥
宏哥

佛印和苏轼打坐

苏轼问:你看看我像什么啊?佛印说:我看你像尊佛。苏轼听后大笑,对佛印说:你知道我看你坐在那儿像什么?就活像一摊牛粪

可惜, 楼主不是苏轼

我知道楼主看不懂宏哥的故事, 因为楼主不是苏轼

BENNEE
BENNEE
曝光一个,其它的不重要
汉克斯
汉克斯
先占个座,要占就占一楼的。最后请 @唐明星 同学把标题改下,今天太晚了先休息了。我明早再来看,最好不是这操蛋的标题了。我不想说脏话。浮躁的年轻人。
放牛娃1988
放牛娃1988
那个帖子你也看了,你自己承认自己看不懂,然后来一句"fuck you",就你这素质,我只好说你是个烂人,然后你说“你说我是烂人,所以也是烂人”,我除了呵呵还能干什么?另外,xml解析的妙论再下表示万分佩服
0
放牛娃1988
放牛娃1988

有这样一个人,他认为在处理XML文件时,Java效率很差,而PHP效率很高,它的理由是:PHP是C扩展,很快;而JAVA引入了一个1mb的包,所以内存占用1mb,所以很慢。

这个说法有多弱智呢?我想指出两点:

1)代码的大小跟内存占用的大小根本没有直接关系,举个简单例子

fopen('/tmp/bigfile');//bigfile大概有1G大小

这段代码只有几十byte,内存占用多少?

2)引入的包不代表最终加载的包的大小,因为不是所有的类都加载

如此弱智错误的人,高举反Java大旗,并且宣称自己“学习Java多年”,岂不让人笑话?可谓烂中至烂矣。

 

0
中山野鬼
中山野鬼

警告楼主!谈论技术无所谓,不要搞人身攻击。 我野鬼一般不发火,发起火来,抡人抡鬼,我都不在乎。你喜欢从技术谈,还是从其他方面谈,让我抡你?

别和我扯中国的程序员的问题!

32789mm3600
32789mm3600
呵呵,鬼哥别动真气哈。 楼主一看就是比较偏激的稍年。。。
0
宏哥
宏哥

引用来自“唐明星”的答案

有这样一个人,他认为在处理XML文件时,Java效率很差,而PHP效率很高,它的理由是:PHP是C扩展,很快;而JAVA引入了一个1mb的包,所以内存占用1mb,所以很慢。

这个说法有多弱智呢?我想指出两点:

1)代码的大小跟内存占用的大小根本没有直接关系,举个简单例子

fopen('/tmp/bigfile');//bigfile大概有1G大小

这段代码只有几十byte,内存占用多少?

2)引入的包不代表最终加载的包的大小,因为不是所有的类都加载

如此弱智错误的人,高举反Java大旗,并且宣称自己“学习Java多年”,岂不让人笑话?可谓烂中至烂矣。

 

脑子进水了, 回去再看看, 是json还是XML?
放牛娃1988
放牛娃1988
跟json和xml有什么关系,难道json你的说法就对了?可笑吧!
0
宏哥
宏哥

再说一遍, 写这种代码的人, 就给他两个字:

滚蛋

 PHP 对这种代码最佳支持,就是应该输出:

FATAL ERROR : FUCK YOU!

放牛娃1988
放牛娃1988
把佛印的故事送给你,真合适
宏哥
宏哥
回复 @皮总 : 很有可能在php6.0实现
皮总
皮总
打个电话给鸟哥,这个提示可以有
0
铂金小猪
铂金小猪
卧槽,你咋就听不明白呢?路上有个水塘,你爹又不是李刚,没那本钱修,那你每次路过时咋办?当然是绕着走咯,难道非得像个傻逼跟,一个水塘过不去?非得跳下去?
空云万里晴
空云万里晴
我觉得应该就事论事,不要这样说,影响不好。
放牛娃1988
放牛娃1988
可是很多人非说没有水塘,而是我眼睛花了,于是我怒了-_-
0
傅小黑
傅小黑

引用来自“铂金小猪”的答案

卧槽,你咋就听不明白呢?路上有个水塘,你爹又不是李刚,没那本钱修,那你每次路过时咋办?当然是绕着走咯,难道非得像个傻逼跟,一个水塘过不去?非得跳下去?
很赞同这个。。。各种语言时而都出现一些莫名其妙的问题,吐槽吐槽就行了。。。语言的问题不影响你写出可靠的优雅的代码。。。php不是也在发展吗,以前都是函数式脚本式跟asp似的,后来php4引入简陋的面向对象,到现在php5引入的比较完善的面向对象机制,还有多重继承、命名空间等等。。。一路上一直是语法bug(姑且说是bug,你理解的)满天飞,不影响他一直发展下去啊。。。当然,php的静态属性和方法的继承直到现在我都不敢恭维,真是稀里糊涂
放牛娃1988
放牛娃1988
谁说不是呢?可是那篇帖子里很多人非说我理解错了,PHP没错,所以我很恼火
0
铂金小猪
铂金小猪
有啥好怒的,大部分人怒的是你这标题。说没水塘的就让他自己跳了试试。规避一些水塘也是好代码的条件之一。
返回顶部
顶部