Ngoài ra, cái này có ngụ ý khác không?
Ngoài ra, cái này có ngụ ý khác không?
Câu trả lời:
Sự khác biệt giữa ngôn ngữ gõ mạnh và ngôn ngữ gõ tĩnh là gì?
Một ngôn ngữ gõ tĩnh có một hệ thống loại được kiểm tra tại thời điểm biên dịch bằng cách thực hiện (trình biên dịch hoặc trình thông dịch). Kiểm tra loại từ chối một số chương trình và các chương trình vượt qua kiểm tra thường đi kèm với một số đảm bảo; ví dụ, trình biên dịch đảm bảo không sử dụng các hướng dẫn số học số nguyên trên các số có dấu phẩy động.
Không có thỏa thuận thực sự về ý nghĩa của "gõ mạnh", mặc dù định nghĩa được sử dụng rộng rãi nhất trong tài liệu chuyên nghiệp là trong ngôn ngữ "gõ mạnh", lập trình viên không thể làm việc xung quanh các hạn chế do hệ thống loại áp đặt . Thuật ngữ này hầu như luôn được sử dụng để mô tả các ngôn ngữ gõ tĩnh.
Đối lập với kiểu gõ tĩnh là "gõ động", có nghĩa là
Ví dụ, Lua , một ngôn ngữ được gõ động, có loại chuỗi, loại số và loại Boolean, trong số các ngôn ngữ khác. Trong Lua, mọi giá trị thuộc về chính xác một loại, nhưng đây không phải là yêu cầu đối với tất cả các ngôn ngữ được nhập động. Trong Lua, cho phép nối hai chuỗi, nhưng không được phép nối chuỗi và chuỗi Boolean.
Trái ngược với "gõ mạnh" là "gõ yếu", có nghĩa là bạn có thể làm việc xung quanh hệ thống loại. C nổi tiếng là được gõ yếu vì bất kỳ loại con trỏ nào cũng có thể chuyển đổi thành bất kỳ loại con trỏ nào khác chỉ bằng cách truyền. Pascal được dự định sẽ gõ mạnh, nhưng sự giám sát trong thiết kế (các bản ghi biến thể không được mã hóa) đã đưa ra một lỗ hổng vào hệ thống loại, vì vậy về mặt kỹ thuật, nó được gõ yếu. Ví dụ về các ngôn ngữ được gõ thực sự mạnh mẽ bao gồm CLU, ML chuẩn và Haskell. Tiêu chuẩn ML trên thực tế đã trải qua nhiều lần sửa đổi để loại bỏ các lỗ hổng trong hệ thống loại được phát hiện sau khi ngôn ngữ được triển khai rộng rãi.
Nhìn chung, hóa ra không hữu ích khi nói về "mạnh" và "yếu". Liệu một hệ thống loại có kẽ hở ít quan trọng hơn số lượng và bản chất chính xác của các lỗ hổng đó, khả năng chúng xuất hiện trong thực tế và hậu quả của việc khai thác lỗ hổng này là gì. Trong thực tế, tốt nhất là tránh các thuật ngữ "mạnh" và "yếu" hoàn toàn , bởi vì
Những người nghiệp dư thường kết hợp chúng với "tĩnh" và "động".
Rõ ràng "gõ yếu" được một số người sử dụng để nói về mức độ phổ biến tương đối hoặc không có chuyển đổi ngầm.
Chuyên gia không thể đồng ý chính xác các điều khoản có nghĩa là gì.
Nhìn chung, bạn không có khả năng thông báo hoặc khai sáng đối tượng của bạn.
Sự thật đáng buồn là khi nói đến các hệ thống loại, "mạnh" và "yếu" không có sự thống nhất chung về ý nghĩa kỹ thuật. Nếu bạn muốn thảo luận về sức mạnh tương đối của các hệ thống loại, tốt hơn là thảo luận chính xác những gì đảm bảo và không được cung cấp. Ví dụ, một câu hỏi hay được đặt ra là: "mọi giá trị của một loại (hoặc lớp) nhất định có được đảm bảo đã được tạo bằng cách gọi một trong các hàm tạo của loại đó không?" Trong C câu trả lời là không. Trong CLU, F # và Haskell là có. Đối với C ++ tôi không chắc chắn tôi muốn biết.
Ngược lại, gõ tĩnh có nghĩa là các chương trình được kiểm tra trước khi được thực thi và một chương trình có thể bị từ chối trước khi bắt đầu. Gõ động có nghĩa là các loại giá trị được kiểm tra trong khi thực hiện và thao tác gõ kém có thể khiến chương trình tạm dừng hoặc báo hiệu lỗi trong thời gian chạy. Một lý do chính cho việc gõ tĩnh là loại trừ các chương trình có thể có "lỗi kiểu động" như vậy.
Có một ngụ ý khác?
Ở cấp độ mô phạm, không, bởi vì từ "mạnh" không thực sự có nghĩa gì cả. Nhưng trong thực tế, mọi người hầu như luôn làm một trong hai điều:
Họ (không chính xác) sử dụng "mạnh" và "yếu" có nghĩa là "tĩnh" và "động", trong trường hợp đó họ (không chính xác) đang sử dụng "gõ mạnh" và "gõ tĩnh" thay thế cho nhau.
Họ sử dụng "mạnh" và "yếu" để so sánh các thuộc tính của hệ thống kiểu tĩnh. Rất hiếm khi nghe ai đó nói về một hệ thống loại động "mạnh" hay "yếu". Ngoại trừ FORTH, không thực sự có bất kỳ loại hệ thống nào, tôi không thể nghĩ đến một ngôn ngữ được gõ động trong đó hệ thống loại có thể bị phá vỡ. Theo định nghĩa, những kiểm tra đó được đưa vào công cụ thực thi và mọi thao tác sẽ được kiểm tra độ tỉnh táo trước khi được thực thi.
Dù bằng cách nào, nếu một người gọi một ngôn ngữ là "gõ mạnh", người đó rất có thể đang nói về một ngôn ngữ được gõ tĩnh.
Điều này thường bị hiểu lầm vì vậy hãy để tôi làm rõ nó.
Gõ tĩnh là nơi loại được liên kết với biến . Các loại được kiểm tra tại thời gian biên dịch.
Gõ động là nơi loại được liên kết với giá trị . Các loại được kiểm tra tại thời gian chạy.
Vì vậy, trong Java chẳng hạn:
String s = "abcd";
s
sẽ "mãi mãi" là a String
. Trong suốt vòng đời của nó, nó có thể trỏ đến các String
s khác nhau (vì s
là một tham chiếu trong Java). Nó có thể có một null
giá trị nhưng nó sẽ không bao giờ đề cập đến một Integer
hoặc a List
. Đó là kiểu gõ tĩnh.
Trong PHP:
$s = "abcd"; // $s is a string
$s = 123; // $s is now an integer
$s = array(1, 2, 3); // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class
Đó là kiểu gõ năng động.
(Chỉnh sửa cảnh báo!)
Gõ mạnh là một cụm từ không có ý nghĩa thống nhất rộng rãi. Hầu hết các lập trình viên sử dụng thuật ngữ này để chỉ một cái gì đó ngoài việc gõ tĩnh sử dụng nó để ám chỉ rằng có một loại kỷ luật được thi hành bởi trình biên dịch. Ví dụ, CLU có một hệ thống loại mạnh không cho phép mã máy khách tạo ra một giá trị của loại trừu tượng trừ khi sử dụng các hàm tạo được cung cấp bởi loại. C có một hệ thống loại hơi mạnh, nhưng nó có thể bị "lật đổ" ở một mức độ vì một chương trình luôn có thể truyền giá trị của một loại con trỏ thành giá trị của loại con trỏ khác. Vì vậy, ví dụ, trong C, bạn có thể lấy một giá trị được trả về malloc()
và vui vẻ chuyển nó sang FILE*
, và trình biên dịch sẽ không cố gắng ngăn bạn hoặc thậm chí cảnh báo bạn rằng bạn đang làm bất cứ điều gì tinh ranh.
(Câu trả lời ban đầu đã nói điều gì đó về một giá trị "không thay đổi loại trong thời gian chạy". Tôi đã biết nhiều nhà thiết kế ngôn ngữ và nhà văn trình biên dịch và chưa biết ai nói về việc thay đổi giá trị trong thời gian chạy, ngoại trừ một số nghiên cứu rất tiên tiến về loại các hệ thống, nơi được gọi là "vấn đề cập nhật mạnh".)
Gõ yếu ngụ ý rằng trình biên dịch không thi hành một đĩa gõ, hoặc có lẽ việc thực thi đó có thể dễ dàng bị lật đổ.
Bản gốc của câu trả lời này kết hợp việc gõ yếu với chuyển đổi ngầm định (đôi khi còn được gọi là "quảng cáo ngầm"). Ví dụ: trong Java:
String s = "abc" + 123; // "abc123";
Đây là mã là một ví dụ về quảng cáo ngầm: 123 được chuyển đổi hoàn toàn thành một chuỗi trước khi được nối với "abc"
. Có thể lập luận rằng trình biên dịch Java viết lại mã đó là:
String s = "abc" + new Integer(123).toString();
Hãy xem xét một vấn đề "bắt đầu bằng" PHP cổ điển:
if (strpos('abcdef', 'abc') == false) {
// not found
}
Lỗi ở đây là strpos()
trả về chỉ số của trận đấu, là 0. 0 bị ép buộc vào boolean false
và do đó điều kiện thực sự đúng. Giải pháp là sử dụng ===
thay vì ==
để tránh chuyển đổi ngầm.
Ví dụ này minh họa cách kết hợp chuyển đổi ngầm định và gõ động có thể khiến các lập trình viên lạc lối.
So sánh với Ruby:
val = "abc" + 123
đó là lỗi thời gian chạy vì trong Ruby, đối tượng 123 không được chuyển đổi hoàn toàn chỉ vì nó được truyền cho một +
phương thức. Trong Ruby lập trình viên phải thực hiện chuyển đổi rõ ràng:
val = "abc" + 123.to_s
So sánh PHP và Ruby là một minh họa tốt ở đây. Cả hai đều là ngôn ngữ được gõ động nhưng PHP có rất nhiều chuyển đổi ngầm định và Ruby (có lẽ đáng ngạc nhiên nếu bạn không quen với nó) thì không.
Điểm ở đây là trục tĩnh / động độc lập với trục mạnh / yếu. Mọi người nhầm lẫn chúng có lẽ một phần bởi vì gõ mạnh và gõ yếu không chỉ được xác định rõ ràng hơn, không có sự đồng thuận thực sự về chính xác những gì có nghĩa là mạnh và yếu. Vì lý do này, gõ mạnh / yếu là màu xám hơn là màu đen hoặc trắng.
Vì vậy, để trả lời câu hỏi của bạn: một cách khác để xem xét điều này gần như đúng là nói rằng gõ tĩnh là an toàn kiểu thời gian biên dịch và gõ mạnh là an toàn kiểu thời gian chạy.
Lý do cho điều này là các biến trong một ngôn ngữ gõ tĩnh có một loại phải được khai báo và có thể được kiểm tra tại thời điểm biên dịch. Một ngôn ngữ được gõ mạnh có các giá trị có một loại trong thời gian chạy và lập trình viên khó có thể lật đổ hệ thống loại mà không có kiểm tra động.
Nhưng điều quan trọng là phải hiểu rằng một ngôn ngữ có thể là Tĩnh / Mạnh, Tĩnh / Yếu, Năng động / Mạnh mẽ hoặc Năng động / Yếu.
"abc" + 123
là lỗi thời gian chạy , không phải lỗi biên dịch trong ruby. Nếu đó là một lỗi biên dịch, ruby sẽ được gõ tĩnh.
Cả hai đều là hai cực trên hai trục khác nhau:
Phương tiện được gõ mạnh , sẽ không được tự động chuyển đổi từ loại này sang loại khác. Gõ yếu thì ngược lại: Perl có thể sử dụng một chuỗi như "123"
trong ngữ cảnh số, bằng cách tự động chuyển đổi nó thành int 123
. Một ngôn ngữ được gõ mạnh như python sẽ không làm điều này.
Có nghĩa là gõ tĩnh , trình biên dịch chỉ ra loại của từng biến tại thời gian biên dịch. Các ngôn ngữ được gõ động chỉ tìm ra các loại biến khi chạy.
Gõ mạnh có nghĩa là có các hạn chế giữa các chuyển đổi giữa các loại. Gõ tĩnh có nghĩa là các loại không động - bạn không thể thay đổi loại biến sau khi nó được tạo.
Ép buộc dữ liệu không nhất thiết có nghĩa là gõ yếu vì đôi khi đường cú pháp của nó:
Ví dụ trên về Java bị gõ yếu vì
String s = "abc" + 123;
Không phải là ví dụ đánh máy yếu vì nó thực sự làm:
String s = "abc" + new Integer(123).toString()
Ép buộc dữ liệu cũng không được gõ yếu nếu bạn đang xây dựng một đối tượng mới. Java là một ví dụ rất tệ về việc gõ yếu (và bất kỳ ngôn ngữ nào có phản xạ tốt rất có thể sẽ không được gõ yếu). Bởi vì thời gian chạy của ngôn ngữ luôn biết loại đó là gì (ngoại lệ có thể là loại bản địa).
Điều này không giống như C. C là một trong những ví dụ tốt nhất về việc đánh máy yếu. Thời gian chạy không có ý tưởng nếu 4 byte là một số nguyên, một cấu trúc, một con trỏ hoặc 4 ký tự.
Thời gian chạy của ngôn ngữ thực sự xác định liệu nó có gõ yếu hay không nếu không nó thực sự chỉ là ý kiến.
EDIT: Sau khi nghĩ thêm, điều này không nhất thiết đúng vì thời gian chạy không nhất thiết phải có tất cả các loại được thống nhất trong hệ thống thời gian chạy để trở thành một hệ thống được gõ mạnh. Haskell và ML có phân tích tĩnh hoàn chỉnh đến mức họ có thể tiềm năng thông tin loại ommit từ thời gian chạy.
Câu trả lời đã được đưa ra ở trên. Cố gắng phân biệt giữa khái niệm mạnh so với tuần và tĩnh so với khái niệm động.
Gõ mạnh: Sẽ không được tự động chuyển đổi từ loại này sang loại khác
Trong Go hoặc Python như các ngôn ngữ được gõ mạnh "2" + 8 sẽ phát sinh lỗi loại vì chúng không cho phép "ép buộc kiểu".
Đánh máy yếu (lỏng lẻo): Sẽ tự động được chuyển đổi sang loại khác: Các ngôn ngữ được nhập yếu như JavaScript hoặc Perl sẽ không gây ra lỗi và trong trường hợp này, JavaScript sẽ dẫn đến '28' và perl sẽ dẫn đến 10.
Ví dụ về Perl:
my $a = "2" + 8;
print $a,"\n";
Lưu nó vào main.pl và chạy perl main.pl
và bạn sẽ nhận được đầu ra 10.
Trong lập trình, lập trình viên xác định kiểu gõ tĩnh và kiểu gõ động đối với điểm mà tại đó các loại biến được kiểm tra. Các ngôn ngữ gõ tĩnh là những ngôn ngữ kiểm tra kiểu được thực hiện tại thời gian biên dịch, trong khi các ngôn ngữ gõ động là những ngôn ngữ kiểm tra kiểu được thực hiện trong thời gian chạy.
Điều này có nghĩa là gì?
Trong Go, nó kiểm tra gõ trước thời gian chạy (kiểm tra tĩnh). Điều này có nghĩa là nó không chỉ dịch và kiểm tra mã mà nó đang thực thi, mà nó sẽ quét qua tất cả các mã và lỗi loại sẽ được ném trước khi mã thậm chí chạy. Ví dụ,
package main
import "fmt"
func foo(a int) {
if (a > 0) {
fmt.Println("I am feeling lucky (maybe).")
} else {
fmt.Println("2" + 8)
}
}
func main() {
foo(2)
}
Lưu tệp này trong main.go và chạy nó, bạn sẽ nhận được thông báo thất bại trong việc biên dịch này.
go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)
Nhưng trường hợp này không hợp lệ đối với Python. Ví dụ: khối mã sau sẽ thực thi cho cuộc gọi foo (2) đầu tiên và sẽ thất bại cho cuộc gọi foo (0) thứ hai. Đó là bởi vì Python được gõ động, nó chỉ dịch và kiểm tra mã mà nó đang thực thi. Khối khác không bao giờ thực thi cho foo (2), vì vậy "2" + 8 thậm chí không bao giờ được nhìn và đối với cuộc gọi foo (0), nó sẽ cố thực hiện khối đó và thất bại.
def foo(a):
if a > 0:
print 'I am feeling lucky.'
else:
print "2" + 8
foo(2)
foo(0)
Bạn sẽ thấy đầu ra sau
python main.py
I am feeling lucky.
Traceback (most recent call last):
File "pyth.py", line 7, in <module>
foo(0)
File "pyth.py", line 5, in foo
print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects
Người này không ngụ ý người kia. Để một ngôn ngữ được gõ tĩnh, điều đó có nghĩa là các loại của tất cả các biến được biết hoặc suy ra tại thời điểm biên dịch.
Một ngôn ngữ được gõ mạnh không cho phép bạn sử dụng một loại như một ngôn ngữ khác. C là một ngôn ngữ được gõ yếu và là một ví dụ tốt về những ngôn ngữ được gõ mạnh không cho phép. Trong C, bạn có thể chuyển một thành phần dữ liệu sai loại và nó sẽ không khiếu nại. Trong các ngôn ngữ gõ mạnh, bạn không thể.
Gõ mạnh có lẽ có nghĩa là các biến có một loại được xác định rõ và có các quy tắc nghiêm ngặt về việc kết hợp các biến của các loại khác nhau trong các biểu thức. Ví dụ: nếu A là số nguyên và B là số float, thì quy tắc nghiêm ngặt về A + B có thể là A được chuyển thành float và kết quả được trả về dưới dạng float. Nếu A là số nguyên và B là một chuỗi, thì quy tắc nghiêm ngặt có thể là A + B không hợp lệ.
Gõ tĩnh có thể có nghĩa là các loại được gán tại thời gian biên dịch (hoặc tương đương với các ngôn ngữ không được biên dịch) và không thể thay đổi trong khi thực hiện chương trình.
Lưu ý rằng các phân loại này không loại trừ lẫn nhau, thực sự tôi sẽ mong đợi chúng xảy ra cùng nhau thường xuyên. Nhiều ngôn ngữ gõ mạnh cũng được gõ tĩnh.
Và lưu ý rằng khi tôi sử dụng từ 'có lẽ' đó là vì không có định nghĩa được chấp nhận phổ biến về các thuật ngữ này. Như bạn đã thấy từ các câu trả lời cho đến nay.