程序=算法+數(shù)據(jù),對(duì)象在哪兒?
如果你認(rèn)可程序=算法+數(shù)據(jù),那么會(huì)發(fā)現(xiàn),對(duì)象好像沒(méi)有存在的必要。
先來(lái)看看算法
按函數(shù)式編程的思路,算法就是把輸入轉(zhuǎn)換成輸出的過(guò)程。
比如常見(jiàn)的各種排序算法,不管過(guò)程如何,都是把沒(méi)有順序的集合轉(zhuǎn)化成有順序的集合的過(guò)程,描述如下:
sort: List -> List
再說(shuō)數(shù)據(jù)
對(duì)于數(shù)據(jù),眾說(shuō)紛紜。最離譜的,是把函數(shù)當(dāng)數(shù)據(jù),沒(méi)有數(shù)據(jù)組織。
下面的例子以js語(yǔ)言描述了這一思想。
// create_user是一個(gè)構(gòu)造函數(shù),但返回的不是對(duì)象,而是函數(shù)。
// 兩個(gè)參數(shù)為:(姓名, 年齡)
let user = create_user("張三", 20)
// 通過(guò)返回函數(shù)的調(diào)用,獲取屬性
// 參數(shù)為屬性名
let name = user("name")
let age = user("age")
create_user的實(shí)現(xiàn)如下:
function create_user(name, age) {
// 返回一個(gè)取屬性值的函數(shù),而非對(duì)象
return function(field_name) {
if (field_name == "name") {
return name
} else if (field_name == "age") {
return age
}
}
}
再一種,是把數(shù)據(jù)當(dāng)一個(gè)個(gè)獨(dú)立的集合,數(shù)據(jù)之間沒(méi)有任何事先聲明的關(guān)系。
關(guān)系數(shù)據(jù)庫(kù)是典型的代表。例如,學(xué)生表與學(xué)生考試表,是兩個(gè)完全獨(dú)立的集合,沒(méi)有具體關(guān)系,所謂外鍵,只是學(xué)生考試表的一個(gè)字段而已。學(xué)生表與學(xué)生考試表,數(shù)據(jù)舉例如下:
學(xué)生表 考試表
學(xué)號(hào) 姓名 學(xué)號(hào) 課程 成績(jī)
001 張三 001 語(yǔ)文 98
002 李四 001 數(shù)學(xué) 88
002 語(yǔ)文 78
數(shù)據(jù)是通過(guò)sql語(yǔ)句,臨時(shí)建立的關(guān)系。例如,下面的sql語(yǔ)句,通過(guò)笛卡爾乘積、篩選把兩個(gè)表之間的關(guān)系建立了起來(lái)。
select * from 學(xué)生表,考試表 where 學(xué)生表.學(xué)號(hào)=考試表.學(xué)號(hào)
第三種,是各種語(yǔ)言都提供的結(jié)構(gòu)體,把數(shù)據(jù)組織成相互關(guān)聯(lián)的網(wǎng)狀結(jié)構(gòu)。
下面的例子用rust語(yǔ)言描述了這個(gè)想法。
struct 學(xué)生 {
name: String,
考試: Vec<考試>
}
struct 考試 {
}
還有其他一些數(shù)據(jù)組織形式,不再贅述。
無(wú)結(jié)構(gòu)數(shù)據(jù)
數(shù)據(jù)除了以上各種組織形式,還有無(wú)組織的,非結(jié)構(gòu)數(shù)據(jù)。比如:
- 程序源碼,程序源碼是無(wú)組織的數(shù)據(jù),這個(gè)觀點(diǎn)很重要??
- 日志文件,日志文件也是沒(méi)有被組織的數(shù)據(jù)。
- 數(shù)據(jù)傳輸,被傳輸?shù)臄?shù)據(jù),很多都沒(méi)有結(jié)構(gòu)。
還有很多。
對(duì)于無(wú)結(jié)構(gòu)數(shù)據(jù),主要觀點(diǎn)是:
- 當(dāng)流對(duì)待!
其次的觀點(diǎn)是:
- 把流轉(zhuǎn)換成有組織的數(shù)據(jù)!
最典型的例子,把程序源碼轉(zhuǎn)換成AST語(yǔ)法樹(shù):
編譯:string -> Tree
對(duì)象是啥
上面的描述過(guò)程沒(méi)有對(duì)象存在。真正面向?qū)ο笈c數(shù)據(jù)無(wú)關(guān),對(duì)象只接收消息,給出反饋。比如,學(xué)生對(duì)象:
let x = 一個(gè)學(xué)生
// set_name是消息名,方法參數(shù)是消息參數(shù)
x.set_name("張")
// get_name是消息名
x.get_name()
嚴(yán)格來(lái)看,對(duì)象不存在屬性,也沒(méi)有數(shù)據(jù)組織,只接收消息,給出反饋。對(duì)象自身是有狀態(tài)的。發(fā)同樣的消息,給出的反饋可能不同。這樣的對(duì)象方式,非常難以控制。