動態類型語言 VS 靜態類型語言
一. 運行期動態修改類型結構
動態編程語言是高級編程語言的一個類別,在計算機科學領域已被廣泛應用。它是一類在運行時可以改變其結構的語言:例如新的函數、對象、甚至代碼可以被引進,已有的函數可以被刪除或是其他結構上的變化。動態語言目前非常具有活力。眾所周知的ECMAScript(JavaScript)便是一個動態語言,除此之外如PHP、Ruby、Python等也都屬于動態語言,而C、C++、Java等語言則不屬于動態語言。
例如下列 Python 代碼:
class Student(object):
def __init__(self, name):
self.name = name
if __name__ == '__main__':
stu = Student("張三")
stu.age = 18 # 運行時,給stu對象新增了一個age屬性,但是在class聲明時未聲明該屬性
def to_string(self):
return f"Student(name={self.name}, age={self.age})"
Student.to_string = to_string # 運行時,給Student類增加了一個 to_string 方法
print(stu.to_string()) # 輸出: Student(name=張三, age=18)
在上述代碼中我們先定義了一個 Student 類,類中聲明了 name 屬性。Python作為動態語言,可以在運行時改變類型的結構,可以為其增加一個age屬性,以及to_string方法。
而作為靜態類型語言的代表 Java、C++、Go 在運行時期就不能修改類的結構。Java 雖然能通過反射機制改變一個類的結構,但其本質仍然是修改源碼,然后重新加載字節碼到內存中,仍然屬于典型的靜態類型語言。
注意:很多人認為解釋型語言都是動態語言,這個觀點是錯的!Java是解釋型語言但是不是動態語言,Java不能在運行的時候改變自己結構。反之成立嗎?動態語言都是解釋型語言。也是錯的!Object-C是編譯型語言,但是他是動態語言。得益于特有的run time機制(準確說run time不是語法特性是運行時環境,這里不展開)OC代碼是可以在運行的時候插入、替換方法的。
二. 類型檢查
對于靜態類型語言,會在編譯器檢查類型是否正確:
public interface Animal {
void run();
}
public class Dog implements Animal {
public void run() {
System.out.prinln("Dog run");
}
}
public class Cat implements Animal {
public void run() {
System.out.prinln("Cat run");
}
}
public class Test {
public void animalRun(Animal animal) {
animal.run();
}
}
Java作為靜態類型語言會在編譯器檢查類型是否正確,所以調用 Test.animalRun 方法時傳入的對象必須是 Animal 類型或者它的子類,否則將編譯報錯。
對于Python這樣的動態語言來說,則不一定需要傳入 Animal 類型。我們只需要保證傳入的對象有一個 run() 方法就可以了:
class Dog(object):
def run(self):
print('Dog run')
這就是動態語言的“鴨子類型”,它并不要求嚴格的繼承體系,一個對象只要“看起來像鴨子,走起路來像鴨子”,那它就可以被看做是鴨子。
Python的“file-like object“就是一種鴨子類型。對真正的文件對象,它有一個read()方法,返回其內容。但是,許多對象,只要有read()方法,都被視為“file-like object“。許多函數接收的參數就是“file-like object“,你不一定要傳入真正的文件對象,完全可以傳入任何實現了read()方法的對象。
本文參考至:
動態語言 - 維基百科,自由的百科全書 (wikipedia.org)

浙公網安備 33010602011771號