class 与构造函数的不同能力

different capability for class with constructor

Data1和Data2的实例具有不同的能力是什么解释?

实例化 Data1 class 的对象的行编译没有问题,但带有 Data2 的行得到的错误是 "right side must be a subtype of left side"

class Data1 
  let _x: U8 = 0

class Data2
  let _x: U8
  new create() => _x = 0

actor Main
  new create(env: Env) =>
    let d1: Data1 iso = Data1
    let d2: Data2 iso = Data2

在 Pony 中,有很多地方可以省略语法或结构的基本元素,并期望它们用隐式默认值填充。关于 Data1Data2 之间区别的问题的答案与隐式默认值的两个示例有关,它们恰好不具有相同的功能。

Data2 class 有一个构造函数,new create() => _x = 0,它有一个隐含的默认接收器能力 ref。也就是说,它隐式扩展为 new ref create() => _x = 0.

Data1class没有构造函数,所以Pony为你创建了一个隐式的默认构造函数,即new iso create()。您的字段声明中的 _x = 0 也会隐式传输到构造函数的主体,但这有点超出您的问题范围。


因此,在这种情况下,分配let d1: Data1 iso = Data1,因为创建的对象将是类型Data1 iso^,可以分配给Data1 iso。分配 let d2: Data2 iso = Data2 不起作用,因为创建的对象将属于 Data2 ref^ 类型,在不破坏隔离保证的情况下无法将其分配给 Data2 iso

Data2 构造函数更改为 new iso create() 是使示例代码正常工作的最佳解决方案。我们不使用 iso 作为构造函数的隐式默认功能,因为它会对构造函数的参数施加额外的约束(它们都必须是可发送的)。


为了完整起见,请注意还有另一种方法可以解决您的问题,即在调用方。如果将构造函数调用放在 recover 块中,则可以 "lift" 到具有更强保证的功能(例如,从 refiso)。这是有效的,因为 recover 块对其中使用的对象引用强制执行其他约束(例如,传递到恢复块的任何引用必须是可发送的),这将支持您提升到的保证。这个作业看起来像:

    let d2: Data2 iso = recover Data2 end