Data1和Data2的实例具有不同功能的解释是什么?
实例化Data1类对象的行编译没有问题,但是Data2的行得到的错误是"右侧必须是左侧的子类型&#34 ;
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
答案 0 :(得分:4)
在Pony中,有很多地方可以省略语法或结构的基本元素,并希望用隐式默认值填充它们。这里关于Data1
和Data2
之间差异的问题的答案与两个隐式默认值的例子有关,这些默认值恰好具有相同的功能。
Data2
类有一个构造函数new create() => _x = 0
,其隐式默认接收器功能为ref
。也就是说,它隐式扩展为new ref create() => _x = 0
。
Data1
类没有构造函数,因此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
块中,则可以“提升”到具有更强保证的功能(例如,从ref
到iso
)。这是有效的,因为recover
块对其中使用的对象引用强制执行其他约束(例如,任何传入recover块的引用必须是可发送的),这将保留您要解除的保证。这个任务看起来像:
let d2: Data2 iso = recover Data2 end