为什么Delphi的记录不能有继承? [英] Why can't Delphi records have inheritance?

查看:166
本文介绍了为什么Delphi的记录不能有继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经想过很长一段时间:为什么不是Delphi记录能够继承(因此所有其他重要的OOP功能)?



基本上使记录是堆的分配版本的类,就像C ++类,并渲染对象(注意:不是实例)过时。我没有看到有什么问题。这也是一个很好的机会来实现记录的前期声明(我仍然对它为什么仍然失踪的困惑)。



你看到这个问题?

解决方案

有关这个问题,有两种继承:接口继承和实现继承。
$ b

接口继承通常意味着多态性。这意味着如果B从A派生,则类型B的值可以存储在类型A的位置。由于切片,这对于值类型(像记录)而不是参考类型是有问题的。如果B大于A,则将其存储在A类型的位置将截断该值 - 在A的定义中添加的任何字段都将丢失。



从这个角度来看,实现继承问题较少。如果Delphi有记录继承,但只有实现,而不是接口,事情不会太糟糕。唯一的问题是,简单地使一个类型A的值为一个类型B的字段做你想要的实现继承的大部分。



另一个问题是virtual方法。虚拟方法分派需要某种每值标签来指示值的运行时类型,以便可以发现正确的重写方法。但记录没有任何地方存储此类型:记录的字段是它拥有的所有字段。对象(旧的Turbo Pascal类)可以有虚拟方法,因为它们有一个VMT:层次结构中定义虚拟方法的第一个对象隐式地添加一个VMT到对象定义的末尾,增长它。但是Turbo Pascal对象具有上述相同的切片问题,这使得它们成为问题。值类型的虚方法有效地需要接口继承,这意味着切片问题。



为了正确支持记录接口继承,我们需要一些解决方案到切片问题。拳击将是一种解决方案,但它通常需要垃圾收集是可用的,它会在语言中引入歧义,在那里可能不清楚是否使用一个值或引用 - 有点像整数vs int在Java与自动装箱。至少在Java中,对于boxed vs unboxedkind的值类型有单独的名称。另一种做拳击的方式就像Google Go的接口,这是一种没有实现继承的接口继承,但需要单独定义接口,并且所有接口位置都是引用。值类型(例如记录)在由接口引用引用时被加框。当然,Go也有垃圾回收。


Something I've wondered for a long time: why aren't Delphi records able to have inheritance (and thus all other important OOP features)?

This would essentially make records the stack-allocated version of classes, just like C++ classes, and would render "objects" (note: not instances) obsolete. I don't see anything problematic with it. This would also be a good opportunity to implement forward declarations for records (which I'm still baffled as to why it's still missing).

Do you see any problems with this?

解决方案

Relevant to this question, there are two kinds of inheritance: interface inheritance and implementation inheritance.

Interface inheritance generally implies polymorphism. It means that if B is derived from A, then values of type B can be stored in locations of type A. This is problematic for value types (like records) as opposed to reference types, because of slicing. If B is bigger than A, then storing it in a location of type A will truncate the value - any fields that B added in its definition over and above those of A will be lost.

Implementation inheritance is less problematic from this perspective. If Delphi had record inheritance but only of the implementation, and not of the interface, things wouldn't be too bad. The only problem is that simply making a value of type A a field of type B does most of what you'd want out of implementation inheritance.

The other issue is virtual methods. Virtual method dispatch requires some kind of per-value tag to indicate the runtime type of the value, so that the correct overridden method can be discovered. But records don't have any place to store this type: the record's fields is all the fields it has. Objects (the old Turbo Pascal kind) can have virtual methods because they have a VMT: the first object in the hierarchy to define a virtual method implicitly adds a VMT to the end of the object definition, growing it. But Turbo Pascal objects have the same slicing issue described above, which makes them problematic. Virtual methods on value types effectively requires interface inheritance, which implies the slicing problem.

So in order to properly support record interface inheritance properly, we'd need some kind of solution to the slicing problem. Boxing would be one kind of solution, but it generally requires garbage collection to be usable, and it would introduce ambiguity into the language, where it may not be clear whether you're working with a value or a reference - a bit like Integer vs int in Java with autoboxing. At least in Java there are separate names for the boxed vs unboxed "kinds" of value types. Another way to do the boxing is like Google Go with its interfaces, which is a kind of interface inheritance without implementation inheritance, but requires the interfaces to be defined separately, and all interface locations are references. Value types (e.g. records) are boxed when referred to by an interface reference. And of course, Go also has garbage collection.

这篇关于为什么Delphi的记录不能有继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆