我正在学习一些F#,并试图弄清楚构造函数是如何工作的。
我想编写一个类,它接受一些输入数据,对其进行分析,并通过成员变量将结果提供给外部世界。解析过程并不简单,所以我希望在此过程中创建一些局部变量,但是如果不将它们变成私有成员变量,我又如何做到这一点呢?使用let创建私有成员变量的almost the same就是使用member private,但我不希望这些临时变量污染对象的命名空间。
到目前为止,这是我能想到的最好的:
type MyClass( inputData ) =
let _parsedData =
// simulate expensive parsing of the input data
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
member this.parsedData = _parsedData
member this.dump () =
// this doesn't compile (as expected)
//printfn "work = %s" work
// I want this to *not* compile (because _parsedData is a local variable in the constructor)
printfn "_parsedData = %s" _parsedData
[<EntryPoint>]
let main argv =
let obj = MyClass "hello, world!"
printfn "obj.parsedData = %s" obj.parsedData
obj.dump()
0 但是_parsedData变成了私有成员变量,这是不必要的,因为它只是一个临时的工作变量,最后的值存储在this.parsedData中。上面链接到的SO post表明,使用let创建的变量将充当局部变量并被丢弃,只要在其他成员中没有引用它们,但是定义this.parsedData返回_parsedData的操作就足以保持_parsedData存活。
我可以使用惰性评估:
let _parsedDataLazy = lazy (
// simulate expensive parsing of the input data
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
)
member this.parsedDataLazy = _parsedDataLazy.Value但是这并没有真正的帮助,因为它仍然存在_parsedDataLazy成为私有成员变量的问题(尽管在这种情况下,这是有意义的)。这种方法还意味着在第一次调用inputData之前保持parsedDataLazy活动,这可能是不可取的/不可能的。
我还想过使用val来定义成员变量,然后执行解析代码来填充它,但是do绑定必须出现在任何member的:-/之前。
我只希望能够在构造函数中使用局部变量,计算值,然后将其存储在对象中。既然已经有了这样的方法,为什么let要创建一个私有成员变量?!构造函数的目的是初始化正在创建的对象,它只是一个函数,因此我不明白为什么在什么时候可以执行代码或不同的行为(例如,如果我使用let在成员函数中定义一个新变量,它就不会作为成员变量被悬挂到对象中)。
另外,如果我使用let在构造函数中创建一个私有成员变量,如下所示:
let _foo = 42然后我就这样访问它:
let member this.printFoo () =
printfn "_foo = %s" _foo // no "this"但如果我像这样创造它:
member private _foo = 42然后我就这样访问它:
let member this.printFoo () =
printfn "_foo = %s" this._foo // uses "this"这种不同的语法表明,前者是在构造函数上创建闭包,并使_foo变量在对象的生命周期内保持活动状态,而不是_foo实际上是对象的成员。这就是真正发生的事吗?
发布于 2022-02-01 09:04:17
要回答@konst-sh的问题:“为什么你认为应该对每个电话进行评估?”,我不认为应该这样做,但这不是我所看到的。
我的理解是,对于下面的代码,组成parsedData的3个语句是一个表达式,它的计算结果是一个字符串(sprintf的输出),该字符串存储在一个成员变量中。
type MyClass( inputData ) =
member this.parsedData =
// simulate expensive parsing of the input data
printfn "PARSE"
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
[<EntryPoint>]
let main argv =
let obj = MyClass "hello, world!"
printfn "CONSTRUCTED"
printfn "obj.parsedData = %s" obj.parsedData
printfn "obj.parsedData = %s" obj.parsedData
0但当我运行它时,我得到了这个:
CONSTRUCTED
PARSE
obj.parsedData = [< hello, world! >]
PARSE
obj.parsedData = [< hello, world! >]我希望看到这样的情况:
PARSE
CONSTRUCTED
obj.parsedData = [< hello, world! >]
obj.parsedData = [< hello, world! >]逐步进入VSCode还可以确认这3条语句被执行了两次。但是parseData不是一个函数,对吗?为此,我需要这样定义:
member this.parsedData () =
...感觉好像我错过了一些最基本的东西。:-)
https://stackoverflow.com/questions/70936102
复制相似问题