在F#中,您可以使用成员函数定义记录,也可以创建类。
type Album = {
Id: int
Name: string
DateReleased: DateTime
Genre: Genre }
with
member this.PrintMessage() =
printf "Hello from %s\n" this.Name
如此使用
let first =
{ Id = 1;
Name = "Hello World!"
Genre = KPop;
DateReleased = DateTime(1991, 8, 12) }
first.PrintMessage()
使用类可能就是这样。
type Album(
Id: int,
Name: string,
DateReleased: DateTime,
Genre: Genre ) as me =
do
me.PrintMessage()
member this.PrintMessage() =
printf "Hello %s" Name
何时方便使用其中一个? 只能通过记录来完成域建模吗?
是否可以通过某些隐藏的FSharp Casting将类转换为记录,反之亦然?
答案 0 :(得分:5)
可以同时使用记录和类来进行域建模。我认为何时使用其中一个主要取决于偏好和环境。我个人通常不使用类,但是我知道有些人经常使用它们。类更多地依赖于突变,并且在易于使用的代价下性能更高。我个人认为,如果要编写面向对象的样式,请使用类;如果要编写功能样式,请使用记录。记录模式匹配和解构更加容易。这种区别的一部分是文化上的,仅仅是因为您可以以特定的方式做某事,并不意味着其他人就能轻松地理解您。代码被编写为供您自己和他人阅读。当您选择记录或类时,它传达有关这些类型的样式和用法的意图。最后,我不知道一个类可以在F#中转换为记录,如果可以的话,我实际上仍然建议不要这样做。这是因为将记录用作类,将类用作记录与这些构造的文化规范相冲突。我个人认为您的示例成员适用于记录和类。我通常喜欢对与给定类型关联的函数使用同名的模块,因为当函数碰巧消耗除记录类型之外的其他东西时,它可以减少混乱。但是,我认为任何有风度的人都不会对那里的任何代码示例感到厌烦。
type Album(
Id: int,
Name: string,
DateReleased: string,
Genre: int ) as me =
let mutable genre = Genre
//readonly property
member val Id = Id
//autoproperty with get and set
member val Name = Name with get, set
member val DateReleased = DateReleased with get, set
//property with explicit get and set
member this.Genre
with get () = genre
and set (value) = genre <- value
答案 1 :(得分:1)
有点麻烦的是,不仅仅是F#记录字段和CLI属性作为数据容器。两者在幕后是相同的:不可变F#记录字段的访问器实现为CLI属性获取器。
如果用例允许,还可以使用带有F#mutable val
定义的CLI字段。另一方面,类似的只读val
定义也由属性获取器公开。
type Album =
// CLI property getter
val Id : int
// mutable CLI field
[<DefaultValue>]
val mutable Name : string
// non-primary constructor with sequence construction (before)
new (id: int, name : string) as me =
{ Id = id } then me.Name <- name
有缺点:
DefaultValueAttribute
它可能被认为是单项的。
答案 2 :(得分:0)
您也可以考虑使用与记录类型同名的模块,如下所示:
type Album = {
Id: int
Name: string
DateReleased: DateTime
Genre: Genre
}
module Album =
let printMessage album =
printfn "Hello from %s" album.Name
let first = {
Id = 1
Name = "Hello World!"
Genre = KPop
DateReleased = DateTime(1991, 8, 12)
}
Album.printMessage first