有没有办法从静态成员访问let绑定字段?以下给出了指示的错误:
type Foo(x) =
let x = x
static member test() =
let foo = Foo(System.DateTime.Now.Month)
printfn "%A" foo.x //the field, constructor or member 'x' is not defined
()
Run Code Online (Sandbox Code Playgroud)
私有显式字段允许从静态成员访问:
type Bar =
val private x:int
new(x) = { x=x }
static member test() =
let Bar = Bar(System.DateTime.Now.Month)
printfn "%A" Bar.x
()
Run Code Online (Sandbox Code Playgroud)
文档http://msdn.microsoft.com/en-us/library/dd469494.aspx声明"显式字段不适合日常使用",但从静态成员访问私有实例字段当然是一种常规方案.此外,我不相信您可以在主构造函数中设置显式字段,这意味着如果需要从静态成员访问一个私有实例字段,则必须将所有字段移动到显式字段,并且您不能再使用主要构造函数 - 它是全有或全无.
作为真实想要从静态成员访问私有实例字段的实际示例,请考虑一个大整数实现:BigInteger类是不可变的,因此大整数的内部表示将保留为私有实例字段(让我们叫它data).现在,假设您认为Add(other)实例方法不适合不可变数据结构,并且您只想实现静态Add(lhs,rhs)方法:在这种情况下,您需要能够访问lhs.data和rhs.data.
我认为你不能这样做......事实上,你不能从其他实例访问let-bound值:
type Foo() =
let x = 3
member this.Test(f:Foo) =
f.x // same error
Run Code Online (Sandbox Code Playgroud)
通常,如果您需要从它所属的实例外部访问这样的值,您应该创建一个私有属性来获取值或使用私有字段.
更新 本规范的第8.6.2节对此进行了介绍.特别是:
实例"let"绑定在词法范围内(因此隐式私有)到正在定义的对象.
也许来自F#团队的人会对这种语言行为的确切答案进行权衡.但是,我可以想到几个潜在的原因:
如前所述,这里是一个大致相同的类定义和创建记录的方法:
type MyClass(i:int) =
let j = i * i
member this.IsSameAs(other:MyClass) =
false // can't access other.j here
type myRecord = { isSameAs : myRecord -> bool }
let makeMyRecord(i:int) =
let j = i * i
{ isSameAs = (fun r -> false) } //obviously, no way to access r.j here
Run Code Online (Sandbox Code Playgroud)
由于F#中的构造函数在概念上类似于返回类型实例的任何其他函数(例如,它们可以在不使用的情况下new调用),因此调用MyClass 5在概念上类似于调用makeMyRecord 5.在后一种情况下,我们显然不希望有任何方法可以j从另一个记录实例访问本地let绑定.因此,在前一种情况下我们也没有任何访问绑定的一致性.
| 归档时间: |
|
| 查看次数: |
1163 次 |
| 最近记录: |