F# 入门(十三):Record(记录)
Record在F#中是一种很重要的用来存贮数据的结构.它与元组和F# 中的枚举(DiscriminatedUnions)差不多,但是又有比他们更方便的地方,如:我们可以很轻松的访问Record中的每个元素的值,而不需要如元组那样做更多的操作才可取得。
下面我们看看Record的定义及与之相关的操作
Record的定义
我们使用type 关键字来定义Record,如我们定义一个名为myRecord的Record:
type myRecord = { Name : string ; Age : int }
在定义这个Record 之后,可以将myRecord当作一个模板,然后照此模板实例化自己的Record.如:
let record1 = { Name = "H";Age = 20 }
let record2 = { Name = "J";Age = 21 }
let record3 = { Name = "K";Age = 24 }
这三个Record均是由模板myRecord实例化而来的,其Interactive运行结果如下:
val record1 : myRecord = {Name ="H"; Age = 20;}
val record2 : myRecord = {Name ="J"; Age = 21;}
val record3 : myRecord = {Name ="K"; Age = 24;}
Record的相关操作——获取元素值
获取Record中元素的值很方便,由于每个元素都如同属性一样,我们可以通过使用Record名字加上.再加元素名即可获取其值,如:record1.Name就可以得到值“H”。
Record的相关操作——复制
有时候我们需要复制一个已知的Record 实例,然后在源Record基础上做小小的改动即可,其实现方法如下:
let copyRecord1 = { record1 with Name ="X" }
这里我们复制了record1,然后仅改动Name的值,其Interactive运行结果如下:
val copyRecord1 : myRecord = {Name= "X"; Age = 20;}
Record的相关操作——为Record添加属性或方法
Record和F# 的枚举一样,我们可以为之添加属性和方法,其方法如下:
type advanceRecord =
{ Name :string; Age : int }
member this.Property = "Hi"
member this.PrintfInfo() = printfn "%s is%d years old" this.Namethis.Age
这里我们定义了一个名为Property的属性,以及一个名为PrintfInfo的方法, 其Interactive 的运行结果为:
type advanceRecord1 =
{Name: string;
Age: int;}
with
member PrintfInfo : unit -> unit
member Property : string
end
使用定义了属性与方法的Record与没有方法与属性的Record没有什么区别。其使用方法和获取元素值的方法一样,如:
let advrcd = { Name = "Z";Age = 24}
advrcd.PrintfInfo()
其运行结果:
Z is 24 years old
Record的相关操作——模式匹配
Record可以做为模式匹配的一部分,这也是Record相比传统数据类型的一项优势,在interactive 中运行下面代码:
type myRecord = { Name : string ; Age : int }
let record1 = { Name = "H";Age = 20 }
let record2 = { Name = "J";Age = 21 }
let record3 = { Name = "K";Age = 24 }
let recordList = [ record1; record2; record3 ]
let result =
recordList
|> List.filter
( function
| {Age = 20} -> true
| _ -> false )
其运行结果为:
val it : myRecord list = [{Name ="H";
Age = 20;}]
Record相对于传统面向对象数据结果的优势
- Record中的元素默认情况下是不可变的,相比类而言更安全
- Record不能被继承,进一步提高了其安全性
- Record可以被用来做模式匹配
- Record可以进行比较,可以使用等号