Khi mình quyết định mình phải hiểu điều gì đó, mình bị ám ảnh cho đến khi cuối cùng mình hiểu ra.
Và gần đây nhất, mình quyết định phải hiểu Static với Dynamic Typing.
Mình cũng đã tìm kiếm các câu trả lời trên Stack Overflow nhưng các giải thích về Static và Dynamic gây nhầm lẫn, dài và thậm chí trái ngược nhau.
Static Vs Dynamic
Hóa ra những thuật ngữ này cũng rất thường bị hiểu lầm, vì thế, quá trình tìm kiếm của mình gặp khá nhiều khó khăn.
Do đó,
Mình đọc bất cứ thứ gì mình có thể tìm thấy nhưng vẫn chưa có gì có thể giải thích thật ngắn gọn, súc tích để mình hiểu được.
Nhưng cuối cùng mình đã ngộ đạo.
Và bây giờ mình sẽ giải thích cho bạn theo cách mà mình đã ngộ ra.
Được biên dịch so với thông dịch
Mã chúng ta viết máy không thể hiểu được.
Do đó, để chạy được, mã cần phải được dịch cho máy hiểu.
Vậy, khi nào mã được dịch?
-
Source Code: Mã nguồn (Đây là các đoạn mã bạn viết)
-
Translation: Chuyển đổi mã nguồn thành thứ mà máy tính có thể đọc (nghĩa là mã máy.
-
Run-time: Khoảng thời gian khi chương trình đang thực thi các lệnh (sau khi biên dịch, nếu nó được biên dịch)
-
Compiled (Biên dịch): Mã được dịch trước khi tiến hành thực thi (run-time)
-
Interpreted (Thông dịch): Mã được dịch khi đang thực thi
Typing là gì?
Khi nào các kiểu được kiểm tra??
"3" + 5
sẽ gây ra lỗi trong ngôn ngữ kiểu strong type, như Java.
Bởi vì ngôn ngữ kiểu strong type không cho phép "ép buộc kiểu" (tự thay đổi kiểu giá trị trong bối cảnh nhất định)
Nhưng trong ngôn ngữ kiểu Weakly type như JavaScript thì lỗi không xảy ra, bạn nhận được kết quả là '35'
-
Static: Kiểm tra kiểu trước thời gian thực thi
-
Dynamic: Kiểm được kiểm tra khi đang thực thi
Các định nghĩa của "Static vs Compiled" và "Dynamic & Interpreted" được giải thích trên google khá giống nhau nhưng bạn chỉ cần nhớ:
-
Khi nào kiểu được kiểm tra?
Lưu ý!
Kiểm tra kiểu không liên quan gì đến ngôn ngữ được biên dịch hoặc thông dịch! Bạn cần tách các thuật ngữ này về mặt khái niệm.
Ví dụ với ngôn ngữ Python
Kết hợp Dynamic và Thông dịch
def myFunction(a):
if a > 0:
print ("Xin chào")
else:
print ("3" + 5)
myFunction(2)
Bởi vì Python được thông dịch và dynamic, nó chỉ dịch và kiểm tra kiểu mã mà nó thực thi.
Thế nên,
Khi gọi myFuntion(2)
Khối else
không bao giờ thực thi, vì vậy "3" + 5
thậm chí không bao giờ được xem xét đến!
Vậy, sẽ ra sao nếu nó là kiểu static?
Một lỗi kiểu sẽ được ném ra trước khi mã chạy.
Nó vẫn thực hiện kiểm tra kiểu trước run-time mặc dù nó được thông dịch.
Vậy, nếu nó được biên dịch thì sao?
Nếu được biên dịch.
Khối else
sẽ được dịch / xem xét trước run-time, nhưng vì nó là kiểu dynamic nên nó sẽ không gây ra lỗi.
Vì các ngôn ngữ kiểu Dynamic không kiểm tra các kiểu cho đến khi thực thi và dòng đó không bao giờ thực thi.
Ví dụ với ngôn ngữ Go
Kết hợp kiểu Static với Biên dịch.
package mainimport ("fmt")
func myFunc(a int) {
if (a > 0) {
fmt.Println("Xin chào")
} else {
fmt.Println("3" + 5)
}
}
myFunc main() {
foo(2)
}
Các kiểu được kiểm tra trước khi chạy (static) và lỗi kiểu (type error) ngay lập tức bị bắt!
Các kiểu vẫn sẽ được kiểm tra trước run-time nếu nó được thông dịch, và kết quả tương tự.
Nếu nó là dynamic, nó sẽ không ném bất kỳ lỗi nào mặc dù mã sẽ được xem xét trong quá trình biên dịch.
So sánh về hiệu suất
Một ngôn ngữ được biên dịch sẽ có hiệu suất tốt hơn trong run-time nếu nó viết kiểu static bởi vì thông tin về kiểu giúp tối ưu mã máy.
Các ngôn ngữ được viết kiểu static có hiệu suất tốt hơn vào run-time về bản chất do không cần phải kiểm tra các kiểu trong khi thực thi (nó đã kiểm tra trước khi chạy).
Tương tự, các ngôn ngữ được biên dịch sẽ nhanh hơn trong run-time vì mã đã được dịch thay vì cần phải thông dịch tại thời điểm run-time.
Giống như bạn có thể nghe hiểu ngoại ngữ khi giao tiếp so với phải nghe qua phiên dịch vậy.
Lưu ý rằng cả hai ngôn ngữ được biên dịch và static sẽ có độ trễ trước khi chạy để dịch và kiểm tra kiểu.
Java là một điển hình về ngôn ngữ được biên dịch và kiểu static do đó hiệu suất của Java rất cao và rất nhiều người chọn Học Java vì điều này.
Một điều khác biệt nữa giữa kiểu Static và Dynamic
Kiểu static bắt lỗi sớm, thay vì tìm thấy chúng trong khi run-time (đặc biệt hữu ích đối với các chương trình lớn).
Nói cách khác, nó nghiêm ngặt hơn kiểu Dynamic.
Nó không cho phép lỗi kiểu ở bất cứ đâu trong chương trình của bạn và thường ngăn các biến tự thay đổi kiểu dữ liệu.
Điều này góp phần kiểm soát các lỗi ngoài ý muốn khi lập trình.
num = 2
num = '3' // ERROR
Kiểu Dynamic linh hoạt hơn giúp tăng hiệu suất công việc cũng như dễ học hơn.
Nhưng kiểu Dynamic không tường minh, nó cho phép các biến tự thay đổi kiểu trong một số bối cảnh nhất định.
Điều này dẫn tới lỗi xảy ra ngoài ý muốn, khó kiểm soát hơn.
Bạn đã hiểu về Static và Dynamic chưa?
Nếu như bạn chưa từng học 2 ngôn ngữ này, bạn có thể sẽ hơi khó hiểu về kiểu Static và Dynamic.
Nhưng mình tin rằng, chỉ cần trả lời được hai câu hỏi "Khi nào mã được dịch?" và "Khi nào các kiểu được kiểm tra?"
Là bạn sẽ hiểu về Static và Dynamic ngay thôi.
---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Dạy học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543 - 0353655150
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
#niit #niithanoi niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python