Make the simple things easy and the complex things possible.
查看文章 |
What are you doing for?
2008年06月25日 星期三 09:49 A.M.
一直以来,感觉搞技术就要虚心、认真,并且负责任! 当然每个人的成长阶段不同,难免出现差别,但这也不能掩盖基本的要求。 早上看到一篇博文,题目:“为什么子类重写父类方法时访问权限不能比父类低?”。 看到这个标题就是一惊,因为PHP中当子类重写父类方法时,其访问权限必须”小于或等于 =》 大于或等于“父类中此方法的访问权限。(PS:是我错了) 出于好奇心,继续看博主的文章,将他的例子摘录过来:
这下倒好,错的不仅是标题,连基本的知识都错了。 在PHP手册中显著的注明了一条:PHP中的__construct()构造函数必须为”public“类型,因为当类被初始化时自动调用__construct()构造函数,这被看做是外部访问。(按照留言,如果是做单件用,我又错了) 错误人人都会有,也许你会觉得不应该写文章来讨论此问题。毕竟学习成长是一个艰苦的过程,需要的不仅仅是自己的毅力,同样需要他人的鼓励和帮助。 但是,如果你看到博主下面的文字,就会觉得我们应该来说些什么,对于博主,对于自己,对于他人。 现有一个类b,他用a继承b类,他又希望a的所有实例能保持单一,所以他打算让a类实现单例模式(关于单例模式以后会专门写一篇文章讨论,如果你不懂这个概念,请直接搜索)。此想法似乎没有任何不妥之处,然后代码运行之后,程序报了错: Fatal error: Access level to a::__construct() must be public (as in class b) in E:\website\test.php on line 29 为什么编译器会报这样的错误?这是因为子类重写父类方法的时候,其访问权限不能比父类低,这意味着:
可是为什么编译器要做这样的限制?这涉及到一个面向对象设计的基础性原则:里矢代换原则(LSP) 如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都被带换成o2时,程序P的行为没有变化,那么类型T2是类T1的子类型。 也就是说,一个软件实体如果使用的是一个基类的话,那么一定适合于其子类,而且它根本不能察觉出基类对象和子类对象的区别。里矢代换原则是继承复用的基石,它是依赖倒转原则(DIP)必须遵循的基本原则,而依赖倒转原则则是实现开放封闭原则(OCP)的主要机制。这即是面向对象三大基本原则的关系。 所以在编译器编译程序的时候,它会去检查一个程序是否符合里矢代换原则,当然这是一个无关业务逻辑,只是简单的语意上的检查。里矢代换原则要求凡是基类型 使用的地方,子类型也一定适用,因此子类必须具备基类型的全部接口。或则说,子类的接口必须包括基类的全部接口,可以再其基础上更宽,但是不能更窄。所以 我们从里矢代换原则来思考本文标题提出的问题,那么就很简单了,b的构造函数__construct()是public类型,而a的构造函数因为要实现单 例模式所以变成了private类型,因此编译器不会让其通过的。 近乎高深的解释(PS:反正我不懂他哪来的这么多高深理论):从PHP脚本错误,到面向对象,再到编译器,最后是软件设计,可谓”洋洋而谈“。如果这在我大学时代,也许我会马上打开google,按照他所说的依次搜索“面向对象” -> ”面向对象设计的基础性原则“ -> ”里矢代换原则“(PS:也许这里google会提示你要找的是不是"里氏代换原则”)-> "依赖反转“ ... 哎,足够多了! 现在你应该看到博主有多么的***让我写这篇文章了吧? 以前总有人说:国内的IT开发气氛有多么的不好,开发人员态度有多么的不端正。 也许这只是一个小小的例子,但需要更多的人去帮助,让这种心态放平稳。 工作固然重要,但对待工作的心态尤其重要。 附注:最后的结论是我错了,在此向博主道歉! |
最近读者: