類通過他們的方法和屬性被賦予內涵。方法是一種動作,屬於動詞,描述類可以做什麼或者它能這樣做;屬性,另一方面,則是形容詞,它有助於類的描述。
一、定義屬性
屬性有三種不同的操作形式:唯讀、只寫、讀寫。屬性的讀操作通過get關鍵字來定義,並且返回屬性的值,而寫操作,則是通過set關鍵字來更新屬性的值。對於定義乙個唯讀的屬性,在語法上只需簡單的定義乙個方法並且無需引數。而另一種方式是,可以提供with get 或者 with set方法,比如下面的示例:
type author =
val mutable id : int
val mutable last_name : string
val mutable first_name : string
// 簡單的定義唯讀屬性
member this.first_name = this.first_name
// 通過with get定義唯讀屬性
member this.first_name1 with get() = this.first_name
// 定義可寫屬性
member this.last_name with set newlist_name = this.last_name <- newlist_name
// 定義可讀可寫屬性
member this.id with get() = this.id
and set newid = this.id <- newid
// 建構函式
new() =
在上篇介紹的類的定義的時候提到過在顯式定義類的時候,無論是字段還是成員,在定義以及引用的時候都需要帶上乙個自我標識字首(隱式定義類是只需要在成員中帶上自我標識字首)。同時,在定義值的時候,由於需要改變值,所以也別忘記了加上mutable關鍵字,否則,定義可寫屬性或者在方法中更新值將會導致編譯異常。
二、在建構函式中設定屬性值
屬性c#的程式設計師應該知道,在c# 3.0提供了可以在建構函式中對屬性進行賦值,如:
//c# **
author author = new author()
同樣,在f#中,也提供了這種簡單的方式來在例項化乙個類的建構函式中對屬性進行初始化:
// f# **
type author() =
let mutable last_name = ""
let mutable first_name = ""
// 定義可寫屬性
member this.last_name with get() = last_name
and set newlist_name = last_name <- newlist_name
member this.first_name with get() = first_name
and set newfirstname = first_name <- newfirstname
然後,例項化物件時,我們就可以這樣寫:
let author = new author(last_name = "jeoo" , first_name = "li")
在這裡,需要注意的是,只有在隱式定義類中才能這樣做,在顯式定義類中,就不能在建構函式中對屬性進行初始化操作。
三、定義方法
在類中定義乙個方法就是在指定自我標識後緊接著定義方法名即可。跟函式一樣,在方法名後的任何形式的規則都是它的引數,如果沒有引數,可以標記為unit 型別,比如下面的**:
type television =
val mutable m_channel : int
val mutable m_turnedon : bool
new() =
// 沒有引數
member this.turnon () =
printfn "turning on..."
this.m_turnedon <- true
member this.turnoff () =
printfn "turning off..."
this.m_turnedon <- false
// 帶有引數
member this.changechannel (newchannel : int) =
if this.m_turnedon = false then
failwith "cannot change channel, the tv is not on."
printfn "changing channel to %d..." newchannel
this.m_channel <- newchannel
除此之外,方法也可以像函式一樣被定義,比如:
type adder() =
member this.addtwoparams x y = x + y
member this.addtwotupledparams (x, y) = x + y
但是,在f#中的定義方法中,不建議利用第一種形式來定義方法,因為在.net的其它語言中並不支援,最好的方法就是所有的引數都被放入乙個元組中,像第二種方式。這樣,當被其它.net語言所引用時,你的f#**看起來不像是乙個單一的元素引數,而是元組中的那個值都是引數。另外,函式與類的方法中乙個小小區別就是類的方法可以遞迴,並且無需採用關鍵字rec
在f#中,方法的過載跟.net其它語言的方法過載規則一樣,比如:
type bitcounter =
static member countbits (x : int16) =
let mutable x' = x
let mutable numbits = 0
for i = 0 to 15 do
numbits <- numbits + int (x' &&& 1s)
x' <- x' >>> 1
numbits
static member countbits (x : int) =
let mutable x' = x
let mutable numbits = 0
for i = 0 to 31 do
numbits <- numbits + int (x' &&& 1)
x' <- x' >>> 1
numbits
static member countbits (x : int64) =
let mutable x' = x
let mutable numbits = 0
for i = 0 to 63 do
numbits <- numbits + int (x' &&& 1l)
x' <- x' >>> 1
numbits
四、靜態方法、屬性、字段
在f#中,如果類中的方法、屬性無需例項物件就能直接訪問,只需要把它標記為static,並且也無需自我標識,類的字段也是如此:
type author() =
let mutable last_name = ""
let mutable first_name = ""
let mutable id = 0
// 靜態字段
static let mutable m_instance = 0
do// 類例項次數
m_instance <- m_instance + 1
member this.last_name with get() = last_name
and set newlist_name = last_name <- newlist_name
member this.first_name with get() = first_name
and set newfirstname = first_name <- newfirstname
member this.id with get() = id
and set newid = id <- newid
override this.tostring() =
system.string.format("author's name is ,id is and the instances is ",first_name,last_name ,id,m_instance)
// 靜態方法
static member findbyid(id) =
printfn "get author by id %d " id
let author = new author(id = id , last_name = "jeooo" , first_name = "li")
author
F 程式設計 物件導向程式設計之訪問修飾符
封裝是類的一大特性,它把抽象的 複雜的事物封裝了在內部,呼叫者無法看到它的內部操作。然而,由於類的呼叫者能夠接觸到類暴露出來的任何屬性和方法,也能夠隨意的修改類的屬性,改變類的狀態,這也導致意外的bug出現。幸好,f 與.net其他的語言一樣,對於類的屬性和方法提供了可訪問控制,允許使用者可以操作哪...
物件導向程式設計之術語
術語 含義屬性 一小段資訊,例如顏色 高度或重量,描述物件的乙個特性 字段物件內部的指定值 操作屬於物件的一段 方法操作的同義詞 訊息從乙個物件傳送到另乙個物件的請求 呼叫執行操作,以響應訊息 執行呼叫的同義詞 關聯兩個物件之間的直接或間接連線 聚合強關聯,隱含著某種部分 一體層次結構 復合強聚合,...
F 函式式程式設計之 面向鐵道程式設計
原文 參考 不長,先看 吧,我在 後面寫講解。type request let validatename request match request with when name error name must not be blank ok request let validateemail fu...