Hãy để tôi cho bạn một ví dụ về sự khác biệt bởi vì chúng KHÔNG giống nhau. Có, điều phối động cho phép bạn chọn đúng phương thức khi bạn đang tham chiếu đến một đối tượng bởi một lớp cha, nhưng phép thuật đó rất cụ thể đối với hệ thống phân cấp lớp đó và bạn phải thực hiện một số khai báo trong lớp cơ sở để làm cho nó hoạt động (các phương thức trừu tượng điền vào các vtables vì chỉ mục của phương thức trong bảng không thể thay đổi giữa các loại cụ thể). Vì vậy, bạn có thể gọi tất cả các phương thức trong Tabby và Sư tử và Hổ bằng một con trỏ Mèo chung và thậm chí có các mảng Mèo chứa đầy Sư tử và Hổ và Tabbys. Nó biết những gì lập chỉ mục các phương thức đó tham chiếu đến vtable của đối tượng tại thời điểm biên dịch (liên kết tĩnh / sớm), ngay cả khi phương thức được chọn tại thời điểm chạy (điều phối động).
Bây giờ, hãy triển khai một mảng có chứa Sư tử và Hổ và Gấu! ((Ôi trời!)). Giả sử chúng ta không có lớp cơ sở được gọi là Animal, trong C ++, bạn sẽ có nhiều việc phải làm vì trình biên dịch sẽ không cho phép bạn thực hiện bất kỳ công văn động nào mà không có lớp cơ sở chung. Các chỉ mục cho các vtables cần phải khớp và không thể thực hiện được giữa các lớp chưa được cấp. Bạn cần phải có một vtable đủ lớn để chứa các phương thức ảo của tất cả các lớp trong hệ thống. Các lập trình viên C ++ hiếm khi coi đây là một hạn chế bởi vì bạn đã được đào tạo để suy nghĩ một cách nhất định về thiết kế lớp. Tôi không nói nó tốt hơn hay tệ hơn.
Với ràng buộc muộn, thời gian chạy sẽ xử lý điều này mà không có lớp cơ sở chung. Thông thường có một hệ thống bảng băm được sử dụng để tìm các phương thức trong các lớp với hệ thống bộ đệm được sử dụng trong trình điều phối. Ở đâu trong C ++, trình biên dịch biết tất cả các kiểu. Trong một ngôn ngữ có giới hạn cuối, các đối tượng tự biết loại của chúng (không phải là không đánh máy, bản thân các đối tượng biết chính xác họ là ai trong hầu hết các trường hợp). Điều này có nghĩa là tôi có thể có các mảng gồm nhiều loại đối tượng nếu tôi muốn (Sư tử và Hổ và Gấu). Và bạn có thể triển khai chuyển tiếp và tạo mẫu tin nhắn (cho phép thay đổi hành vi trên mỗi đối tượng mà không cần thay đổi lớp) và tất cả các loại khác theo những cách linh hoạt hơn nhiều và dẫn đến ít chi phí mã hơn so với các ngôn ngữ không hỗ trợ ràng buộc muộn .
Bạn đã bao giờ lập trình trong Android và sử dụng findViewById ()? Bạn hầu như luôn kết thúc việc ép kiểu kết quả để có được kiểu phù hợp, và việc ép kiểu về cơ bản nằm ở trình biên dịch và từ bỏ tất cả tính tốt của việc kiểm tra kiểu tĩnh được cho là làm cho ngôn ngữ tĩnh vượt trội hơn. Tất nhiên, thay vào đó bạn có thể có findTextViewById (), findEditTextById () và một triệu người khác để các kiểu trả về của bạn khớp nhau, nhưng điều đó đang ném tính đa hình ra ngoài cửa sổ; được cho là toàn bộ cơ sở của OOP. Một ngôn ngữ bị ràng buộc muộn có thể cho phép bạn lập chỉ mục đơn giản theo một ID và coi nó như một bảng băm và không cần quan tâm đến kiểu đang được lập chỉ mục hay được trả về.
Đây là một ví dụ khác. Giả sử rằng bạn có đẳng cấp Sư tử và hành vi mặc định của nó là ăn thịt bạn khi bạn nhìn thấy nó. Trong C ++, nếu bạn muốn có một sư tử "được huấn luyện", bạn cần tạo một lớp con mới. Việc tạo mẫu sẽ cho phép bạn thay đổi một hoặc hai phương pháp của Sư Tử cụ thể đó cần được thay đổi. Đó là lớp và kiểu không thay đổi. C ++ không thể làm điều đó. Điều này rất quan trọng vì khi bạn có một "AfricanSpottedLion" mới kế thừa từ Lion, bạn cũng có thể huấn luyện nó. Việc tạo mẫu không thay đổi cấu trúc lớp để nó có thể được mở rộng. Đây thông thường là cách các ngôn ngữ này xử lý các vấn đề thường yêu cầu đa kế thừa, hoặc có lẽ đa kế thừa là cách bạn xử lý việc thiếu nguyên mẫu.
FYI, Objective-C là C với thông điệp của SmallTalk được thêm vào và SmallTalk là OOP ban đầu và cả hai đều bị ràng buộc muộn với tất cả các tính năng ở trên và hơn thế nữa. Các ngôn ngữ bị ràng buộc muộn có thể chậm hơn một chút so với quan điểm ở cấp vi mô, nhưng thường có thể cho phép mã được cấu trúc theo cách hiệu quả hơn ở cấp vĩ mô và tất cả đều được ưu tiên.