PHP中虚函数的正确实现?
在我的工作场所(仅限 php),我们有一个数据库抽象的基类。当您想要向基础层添加新的数据库表时,您必须创建该基类的子类并重写一些方法来定义使用该表的单独行为。正常行为应该保持不变。
现在我在我们公司见过很多新程序员,他们只是重写默认行为的方法。有些人是如此“好”,可以放入所有默认行为,只需在他们喜欢的地方添加单独的东西,其他人则在尝试使用基类及其继承者时自杀。
为了解决这个问题,我的第一个想法是考虑应该通过继承类重写的抽象方法。但除了反对抽象方法的其他论点之外,“抽象”只是没有说明为什么基类不能被它自己使用以及为什么这些函数应该被重写。
经过一番谷歌搜索后,我没有找到在 php 中实现“真正的”虚函数的好答案(只是有一个虚函数,这几乎消除了具体实现的所有希望)。
那么,对于这件事,你会怎么做呢?
at my working place (php only) we have a base class for database abstraction. When you want to add a new database table to the base layer, you have to create a subclass of this base class and override some methods to define individual behaviour for using this table. The normal behaviour should stay the same.
Now I have seen many new programmers at our company, who just override the method for the default behaviour. Some are so "nice" to put in all the default behaviour and just add there individual stuff where they like it, others kill themself trying to use the baseclass and their inheritor.
My first thought to solve this problem, was thinking about abstract methods that should be overriden by inheriting classes. But beside other arguments against abstract methods, "abstract" just does not show why the baseclass can't be used by its own and why these function should be overriden.
After some googling around I didn't find a good answer to implementing "real" virtual functions in php (just that there is a virtual function, that nearly kills all hope of a concrete implementation).
So, what would you do with this matter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 PHP 中,所有公共和受保护函数都是“虚拟”的。您可以通过在前面添加 final< 来防止函数被覆盖/strong> 关键字。 (或者将它们设为私有,但这可能是一个坏主意)。
在基类的设计中,我会考虑子类想要影响的行为。
例如,我会创建空函数,例如 before_update() 和 after_insert()。
当更新/插入事件发生时,基类将调用它。
也许 is_valid() 函数在基类中总是返回 true,并使用注释块来描述当子类返回 false 时的后果。
希望这能给您一些启发。
In PHP all public and protected functions are "virtual". You can prevent functions from being overriden by prepending the final keyword. (Or by making them private, but this is probably a bad idea).
In the design of the baseclass I would think of behaviors that subclasses would want to affect.
I would for example create empty functions like before_update() and after_insert().
Which the baseclass will call when an update/insert event occurs.
Maybe an is_valid() function which always returns true in the baseclass, and use the commentblock to describe what the consequences are when a subclass return false.
Hopefully this would give you some inspiration.
如果人们以错误的方式使用该类,您始终可以使用“final”关键字来防止某些类函数被覆盖。
在我看来,他们无法实现某些功能,因此重写了这些方法。您可能需要看看您的课程的设计。
You can always use the "final" keyword to prevent some of the classes functions from being overridden if people are using the class in the wrong way.
It sounds to me like they are unable to acheive certain functionality hence overriding the methods. You may need to take a look at the design of your classes.
如果没有基类的实现示例,就很难提供具体信息。但我想到了一些事情:
数据库抽象首先是复杂的东西。我理解你想保持精简、干净和刻薄,但我认为这非常困难。您确实必须彻底了解不同数据库引擎的规格,以了解哪些部分是通用的,哪些部分需要专门化。还;当您谈论通过扩展基类添加数据库表时,您确定没有将数据库抽象与表数据网关模式混合在一起吗?
如果扩展类也竭力保持干净,那么当前基类的方法可能做得太多和/或不够通用。也许您应该将基类接口方法分解为更小的受保护方法,这些方法足够通用,可以在扩展类的重写方法中重用?反之亦然:也许您应该在接口方法中挂钩到可重写的方法。
最后,也许您应该只强制实现一个接口,而不是扩展基类?
Without an example of the implementation of your base class, it's hard to give concrete info. But a few things come to mind:
Database abstraction is complex stuff to begin with. I understand that you want to keep it lean, clean and mean, but I think it's pretty darn difficult. You really have to take a thorough look at the specs of different DB engines to see what parts are general and what parts need specialization. Also; are you sure you don't have DB abstraction mixed up with the Table Data Gateway pattern, as you are talking about adding DB tables by extending the base class?
The methods of your current base class might be doing too much and/or are not general enough to begin with, if the extended classes are bending over backwards too keep it clean. Maybe you should break the base class interface methods up in smaller protected methods that are general enough to be reused in the overriding methods of the extended classes? Or vice versa: maybe you should have hooks to overridable methods in your interface methods.
Following from point 2: What's wrong with having an abstract class with some general implemented methods, and let your vanilla class (your base class) and other classes inherit from that?
Lastly, maybe you should just enforce an interface to be implemented, in stead of extending the base class?