【发布时间】:2015-05-10 18:45:11
【问题描述】:
假设我有这样定义的记录...
type Employee = {Name : string; Salary : int}
我想要另一种固定Salary 的类型。我想说...
type Manager = {Name: string; Salary : int = 250000}
...但我好像做不到。
我有什么选择来获得这种行为?
【问题讨论】:
标签: inheritance f# recordtype
假设我有这样定义的记录...
type Employee = {Name : string; Salary : int}
我想要另一种固定Salary 的类型。我想说...
type Manager = {Name: string; Salary : int = 250000}
...但我好像做不到。
我有什么选择来获得这种行为?
【问题讨论】:
标签: inheritance f# recordtype
你可以给你的记录一个只读属性:
type Manager =
{
Name: string
}
member this.Salary = 250000
FSI 示例:
> let m = { Name = "Foo" };;
val m : Manager = {Name = "Foo";}
> m.Name;;
val it : string = "Foo"
> m.Salary;;
val it : int = 250000
【讨论】:
with?或者写这篇文章时可能不需要with?今天试的时候,没有with就不行。
= 之后有左大括号。这样做,with 是必需的,但是完全按照上面的方式使用大括号,这不是必需的。
F# 记录是不可变的,因此所有字段值都是“固定的”,用您的话来说。
如果您的目标是避免在构造时指定Salary,最简单的方法是创建一个“构造函数”:
type Manager = {Name : string; Salary : int} with
static member Make name =
{Manager.Name=name; Salary=250000}
注意1.我使用Manager.Name,这样它就不会干扰Employee的构造;
注意 2。此外,这种方法甚至不会阻止保持单一类型 Employee 也将优雅地处理 Manager 的创建;只需调用该方法,例如MakeManager 为清楚起见。
static 方法不会禁止某人(使用您的库的开发人员)手动创建工资错误的Manager。请参阅this answer 了解如何防止此类创建。
【讨论】:
记录类型可以有成员,例如
type Employee = {Name : string; Salary : int}
type Manager =
{Name: string; }
member x.Salary with get() = 250000
let manager1 = {Manager.Name = "manager1"}
let manager2 = { manager1 with Manager.Name = "manager2"}
let salary = manager1.Salary // fsi: val salary : int = 250000
但在这里,如果经理是雇员,我会使用普通的类和继承而不是记录。使用 F# 中的普通类是完全可以的,并且可以通过避免公共 setter 来实现不变性。
【讨论】: