Delphi:可维护性虚拟与虚拟抽象
几个月前我写了一堆代码,现在我正在向其中添加一些东西。我意识到我编写了一堆函数,这些函数源自一个类,该类的函数大约有 2/3 是抽象函数,其余 1/3 是虚拟函数。
我非常厌倦看到:
function descendent.doSomething() : TList;
begin
inherited;
end;
当我为基类提供了这个:
function descendent.doSomething() : TList;
begin
result := nil;
end;
并讨厌最终得到:
function descendent.doSomething() : TList;
begin
end;
然后想知道为什么有些东西不起作用。
我喜欢使用抽象函数,因为编译器会告诉您是否因为没有实现某些函数而可能出现抽象错误。
我的问题是,因为我仍然是一个相对较新的 Delphi 程序员,而且 8 年来我从来没有维护过任何东西,是否值得花时间 以这种方式修剪你的代码(即删除刚刚继承的函数并将基类函数从抽象更改为具体)
I was writing a bunch of code a few months ago and now I'm adding stuff to it. I realized I wrote a bunch of functions that descend from a class that has about 2/3rds of its functions abstract and the remaining 1/3rd virtual.
I'm pretty much sick of seeing:
function descendent.doSomething() : TList;
begin
inherited;
end;
when I've got this for the base class:
function descendent.doSomething() : TList;
begin
result := nil;
end;
and would hate to wind up with:
function descendent.doSomething() : TList;
begin
end;
and then wonder why something didn't work.
I like using abstract functions because the compiler will let you know if you're liable to get an abstract error because you didn't implement some functions.
My question is, because I'm still a relatively new Delphi programmer and I've never had to maintain anything 8 years hence, is it worth taking the time to prune your code in this manner (i.e. remove functions that just have inherited in them and change your base class functions from abstract to concrete)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一如既往,这取决于问题。我使用接口来定义一组类的用户界面。至少当我知道我将拥有多个底层实际类的实现时。例如,您可以有这样的内容:
在这里您没有共同的祖先。每个类仅实现接口,没有公共基类形式的公共底层结构。如果实现如此不同以至于它们不共享任何东西,但他接口本身,这是可能的。您仍然需要使用相同的接口,以便与派生类的用户保持一致。
第二个选项是:
这里你有一个所有类的基类。在该类中,您可以具有公共属性或事件其他类等...但是所有过程都被标记为抽象,因为它们不执行任何常见任务。 Abstract 确保它们将在派生类中实现,但您不需要在每个类中实现“FieldA”,只需在“TAllAbstract_Custom”中实现它。这确保了 DRY 原则的使用。
最后一个选项是:
这里所有派生类都有一个公共的基本虚拟过程。这确保您不必在派生类级别实现每个过程。您只能覆盖代码的某些部分,或者根本不覆盖。
当然,这都是边缘情况,它们之间还有空间。您可以混合使用这些概念。
请记住:
很抱歉回答很长,但我无法在这里给出简单的解释,因为没有。这一切都取决于当前的问题。它是派生类有多少共同点和它们的实现有多少不同之间的平衡。
It depends on the problem as always. I use interfaces to define the user interface for the set of classes. At least when I know I will have more than one implementation of the underlying actual class. For instance You can have something like this:
Here you dont have a common ancestor. Each class only implements the interface and has no common underlying structure in a form of a common base class. This is possible if implementations are so different that they do not share anything, but he interface itself. You still need to use the same interface so you are consistent towards the users of the derived classes.
The second option is:
Here you have a base class for all the classes. In that class you can have common properties or event other classes etc... But all procedures are marked as abstract because they do not perform any common tasks. Abstract ensures the they will be implemented in the derived classes, but you do not need to implement "FieldA" in every class, you only implement it in the "TAllAbstract_Custom". This ensures that the DRY principle is used.
The last option is:
Here all derived classes have a common base virtual procedure. This ensures you do not have to implement every single procedure at the level of the derived classes. You can only override some parts of the code or none at all.
Naturally this are all edge cases, there is room in beetwen them. You can have a mix of those concepts.
Just remember:
Sorry for a long answer but I could not give an easy explanation here because there is none. It all depends on the problem at hand. It is a balance between how much do the derived classes have in common and how different their implementations are.
如果代码真的很简单,并且您发现很难阅读并且容易出错,那么它可能就很难阅读并且容易出错。 (另一方面,如果代码复杂并且您发现难以阅读,这可能是您缺乏经验。但不是这样的。)您可能会很好地重构它现在,虽然这个问题在你的脑海中仍然记忆犹新。
If the code is really simple and you find it difficult to read and error-prone, then it's probably difficult to read and error-prone. (On the other hand, if the code is complicated and you find it hard to read, it could be your lack of experience. But not something like this.) You'd probably do well to refactor it now, while the issue is still fresh in your mind.
是的,修剪你的代码。
它使您的其他代码更易于阅读(正如您已经提到的,更容易看到哪些方法实际上被覆盖)。作为一项额外的好处,更改父类中方法的签名会更容易:想象一下,您决定再向虚拟方法传递一个参数;您对父类进行更改,然后需要对从给定父类继承的每个子类重复相同的更改。那时,您不希望只调用“继承”的虚假覆盖方法!
Yes, prune your code.
It makes your other code much easier to read (as you already mentioned, it would be easier to see what methods are actually overwritten). As an added benefit it will be easier to change the signature of the method in the parent class: Imagine you decide to pass one more parameter to a virtual method; You make the change to the parent class, then you'll need to repeat that same change for every child class that inherits from the given parent class. At that point you don't want bogus overwritten methods that just call "inherited"!