1. 程式人生 > >對程式設計的一些感悟

對程式設計的一些感悟

從2002年接觸C語言開始,不知不覺程式設計已經伴隨我14年了,這期間或多或少的使用了C,C++,C#,Java,PHP,JavaScript, bash, VBA這些常見的開發語言,可悲的是才疏學淺,只是略懂而已。

1 程式設計的本質沒變

程式=資料結構+演算法,這是對程式最本質的、最切中要害的、最簡潔的闡述。
一直以來,我有一個習慣,就是在理解一個抽象概念的時候,一定要找到這個概念的一個具體實現。資料結構和演算法就是抽象的概念,我們不妨用C系語言的具體實現來重新定義程式,那就是:程式=結構體+函式。

資料結構和演算法是彼此影響的,在設計的時候,很難嚴格的分階段進行。如果說那個更重要,我會毫不猶豫的說:資料結構要比演算法重要!

。這是因為,資料結構設計的好壞,直接影響到演算法的實現難易、優雅程度。Linux之父也闡述過類似的觀點。

在機器指令級別上,大多數機器都為函式定義、呼叫(CALL指令)、資料結構定義提供了直接的支援。

資料結構和演算法的結合方式,造就了形形色色的程式語言和程式設計思想。

2 純面向物件

純面向物件把演算法、資料結構進行了兩方面的彼此聯絡。
(1)函式必須施加到特定的資料結構上
任何一個函式的內部,都可以通過一個特定的指標(如this)來得到要對齊進行操作的資料結構。

(2)函式(地址)本身就是資料結構的成員
任何一個函式都被一個數據結構的成員引用,沒有獨立存在的函式。

Java,JavaScript,C#就是純面向物件的語言,在這些語言裡,(1)函式一定是成員函式;(2)函式內部一定有一個指向資料結構的指標。

在使用純面向物件的語言進行程式設計時:
(1)每定義一個函式時,首先要確定這個函式是哪個類(或者物件)的成員;
(2)每呼叫一個函式時,首先要確定函式內的this指標到底指向了哪個物件。

在使用JavaScript時,注意:一個物件的成員函式內的this指標可能指向另外一個物件。

<script type="text/javascript">
var a = {
    name: "a",
        f: function(){
          alert(this.name);
      }
};
var b = {name: "b"};

a.f.apply(b);

</script>

3 基於類與基於原型

面向物件的實現主要有兩種方式,一是基於類、二是基於原型。

C++,JAVA,PHP等採用的是基於類的實現方式,在這些語言裡,使用物件之前必須要定義描述物件的型別。在這種方式下,子類物件擁有父類物件的完整副本,父類物件、多個子類物件、彼此獨立。

#include <stdio.h>

class A
{
    public:
        int x;
};

class B : public A
{
};

int main()
{
    A a;
    a.x = 10;

    B b;
    b.x = 20;

    printf("%d,%d\n", a.x, b.x);
    return 0;
}

在基於類的語言中,只有父類子類的概念,沒有父物件、子物件的概念。

JavaScript則採用了基於基於原型的方式。在JavaScript裡,沒有類的概念,任何一個物件內部都有一個指向父物件的指標proto。子物件只是包含了父物件的指標,並沒有父物件的副本。所有的子物件共享一份父物件。

<script type="text/javascript">
var a = {};
var b = {};
a.__proto__.x = 10;

alert(b.x);
alert(Object.x);
</script>

在基於原型的語言中,沒有類的概念,只有父物件、子物件的概念。

4 靜態型別和動態型別

傳統的C/C++是靜態型別語言的典型代表,對於編譯型語言來說,編譯時(程式執行之前)必須確定資料的型別,所以只能採用靜態型別。

PHP,JavaScript則是動態型別語言,大多數解釋性語言都採用動態型別。執行時由直譯器負責根據實際的資料來確定儲存的具體型別。

無論靜態型別還是動態型別的語言,其程式在執行的時候,任何資料都必須是確定的型別。

5 執行時可變的資料結構

JavaScript的物件屬性、陣列元素可以在執行時動態增減,PHP的物件成員、陣列元素也可以執行時動態增減。這種執行時可變的資料結構給程式設計帶來了很大的便利。雜湊表是實現這種可變資料結構的關鍵。