这本质上将记录堆栈分配的类的版本,就像C类一样,并且将渲染“对象”(注意:不是实例)过时。我没有看到任何问题。这也将是一个很好的机会来实施向前宣布的记录(我仍然为什么仍然缺少我的疑虑)。
你看到有什么问题吗?
解决方法
界面继承通常意味着多态性。这意味着如果B是从A派生的,则类型B的值可以存储在A类的位置。对于值类型(如记录)而言,这是与参考类型相对的,因为切片是有问题的。如果B大于A,则将其存储在类型A的位置将截断该值 – 任何在其定义中添加的B超过A的字段将丢失。
从这个角度来看,实现继承不太有问题。如果Delphi具有记录继承,但只有实现,而不是接口,事情不会太糟糕。唯一的问题是,只要将类型A的值设置为类型B的字段,就可以执行大部分的实现继承。
另一个问题是虚拟方法。虚拟方法调度需要某种类型的每值标签来指示值的运行时类型,以便可以发现正确的覆盖方法。但记录没有任何地方存储这种类型:记录的字段是它所有的字段。对象(旧的Turbo Pascal类)可以具有虚拟方法,因为它们具有VMT:层次结构中定义虚拟方法的第一个对象会将VMT添加到对象定义的末尾,从而增加它。但是Turbo Pascal对象具有与上述相同的切片问题,这使得它们成为问题。价值类型的虚拟方法有效地需要接口继承,这意味着切片问题。
所以为了正确支持记录接口继承,我们需要一些解决方案来解决切片问题。拳击将是一种解决方案,但通常需要垃圾收集才能使用,并且会在语言中引入歧义,在这里您可能不清楚是否使用值或引用 – 有点像Integer vs在Java中使用自动装箱。至少在Java中,值类型的“盒装”和“未装箱的”种类有不同的名称。另一种做拳击的方式就是Google Go与其接口,这是一种接口继承而没有实现继承,但需要单独定义接口,并且所有接口位置都是引用。值类型(例如记录)在由接口引用引用时被包装。当然还有垃圾收集。