Sự khác biệt giữa Ràng buộc sớm và Trễ là gì?


81

Sự khác biệt giữa ràng buộc sớm và muộn là gì?



4
Tôi có sai khi nói sớm = lệnh gọi hàm trực tiếp trong khi late = lệnh gọi hàm thông qua con trỏ hàm? Tôi không bao giờ hết ngạc nhiên về việc các lập trình viên có cách tiếp nhận các khái niệm đơn giản và làm cho chúng có vẻ phức tạp hơn nhiều (như một biểu hiện của trí thông minh?). Lập trình vốn dĩ là một lĩnh vực nghiên cứu rất dễ dàng cho đến khi bạn đi sâu vào những thứ như cách tạo kiểu float hay sự phát triển của trình biên dịch.
Bob Blogge

Có thể có bản sao của ràng buộc Sớm và muộn
berkay

Câu trả lời:


57

Câu trả lời ngắn gọn là ràng buộc sớm (hoặc tĩnh) đề cập đến ràng buộc thời gian biên dịch và ràng buộc muộn (hoặc động) đề cập đến ràng buộc thời gian chạy (ví dụ: khi bạn sử dụng phản chiếu).


8
Nhưng bài báo trên wikipedia về tính liên kết muộn ( en.wikipedia.org/wiki/Late_binding ) nói rằng "Liên kết muộn thường bị nhầm lẫn với công văn động, nhưng có sự khác biệt đáng kể". Vậy chúng có giống nhau hay không? Nếu chúng giống nhau, thì trang wikipedia đó cần được thay đổi.
Alexander Bird

2
Better stackoverflow trả lời ở đây stackoverflow.com/questions/484214/early-and-late-binding
Baggers

18

Trong các ngôn ngữ biên dịch, sự khác biệt là rõ ràng.

Java:

//early binding:
public create_a_foo(*args) {
 return new Foo(args)
}
my_foo = create_a_foo();

//late binding:
public create_something(Class klass, *args) {
  klass.new_instance(args)
}
my_foo = create_something(Foo);

Trong ví dụ đầu tiên, trình biên dịch có thể thực hiện tất cả các loại nội dung gọn gàng tại thời điểm biên dịch. Trong điều thứ hai, bạn chỉ cần hy vọng rằng bất cứ ai sử dụng phương pháp này sẽ làm như vậy một cách có trách nhiệm. (Tất nhiên, các JVM mới hơn hỗ trợ Class<? extends Foo> klasscấu trúc, điều này có thể làm giảm đáng kể rủi ro này.)

Một lợi ích khác là IDE có thể liên kết nóng đến định nghĩa lớp, vì nó được khai báo ngay tại đó trong phương thức. Lệnh gọi tới create_something (Foo) có thể khác rất xa với định nghĩa phương thức và nếu bạn đang xem định nghĩa phương thức, có thể rất hay khi thấy cách triển khai.

Ưu điểm chính của tính năng liên kết muộn là nó làm cho những thứ như đảo ngược điều khiển dễ dàng hơn, cũng như một số cách sử dụng đa hình và gõ vịt (nếu ngôn ngữ của bạn hỗ trợ những thứ như vậy).


6

Lấy trực tiếp từ http://word.mvps.org/fAQs/InterDev/EarlyvsLateBinding.htm

Có hai cách để sử dụng Tự động hóa (hoặc Tự động hóa OLE) để điều khiển một ứng dụng khác theo chương trình.

Liên kết muộn sử dụng CreateObject để tạo và thể hiện của đối tượng ứng dụng, sau đó bạn có thể kiểm soát. Ví dụ: để tạo một phiên bản Excel mới bằng cách sử dụng liên kết muộn:

 Dim oXL As Object
 Set oXL = CreateObject("Excel.Application")

Mặt khác, để thao tác một phiên bản Excel hiện có (nếu Excel đã được mở), bạn sẽ sử dụng GetObject (bất kể bạn đang sử dụng liên kết sớm hay muộn):

 Dim oXL As Object
 Set oXL = GetObject(, "Excel.Application")

Để sử dụng tính năng liên kết sớm, trước tiên bạn cần đặt một tham chiếu trong dự án của mình cho ứng dụng bạn muốn thao tác. Trong VB Editor của bất kỳ ứng dụng Office nào hoặc trong chính VB, bạn thực hiện việc này bằng cách chọn Tools + References, và chọn ứng dụng bạn muốn từ danh sách (ví dụ: “Microsoft Excel 8.0 Object Library”).

Để tạo một phiên bản Excel mới bằng cách sử dụng liên kết sớm:

 Dim oXL As Excel.Application
 Set oXL = New Excel.Application

Trong cả hai trường hợp, ngẫu nhiên, trước tiên bạn có thể cố gắng lấy một phiên bản Excel hiện có và nếu điều đó trả về lỗi, bạn có thể tạo một phiên bản mới trong trình xử lý lỗi của mình.


3
Tôi biết câu trả lời này đã cũ và được lấy từ một nơi khác, nhưng nó không chính xác. Liên kết muộn ngụ ý sử dụng CreateObject, nhưng CreateObject không nhất thiết ngụ ý ràng buộc muộn. Ràng buộc không áp dụng cho phương pháp khởi tạo một đối tượng, chỉ áp dụng cho cách nó được khai báo. Nếu bạn khai báo đối tượng của mình là "As Excel.Application" thì không quan trọng bạn khởi tạo nó như thế nào. Tôi luôn sử dụng CreateObject để khởi tạo các tham chiếu đối tượng đến các thư viện bên ngoài, bằng cách đó tôi có thể chuyển đổi giữa ràng buộc sớm và cuối và chỉ phải chuyển một dòng (không phải hai) - dòng khai báo đối tượng.
JimmyPena 14/10/11

6

Câu trả lời tương tự nhưng chi tiết hơn từ cuốn sách Herbert Schildt C ++: -

Liên kết sớm đề cập đến các sự kiện xảy ra tại thời điểm biên dịch. Về bản chất, liên kết sớm xảy ra khi tất cả thông tin cần thiết để gọi một hàm được biết đến tại thời điểm biên dịch. (Nói cách khác, liên kết sớm có nghĩa là một đối tượng và một lệnh gọi hàm được ràng buộc trong quá trình biên dịch.) Ví dụ về liên kết sớm bao gồm các lệnh gọi hàm bình thường (bao gồm các hàm thư viện chuẩn), các lệnh gọi hàm quá tải và các toán tử được nạp chồng. Ưu điểm chính của việc ràng buộc sớm là hiệu quả. Bởi vì tất cả thông tin cần thiết để gọi một hàm được xác định tại thời điểm biên dịch, các loại lệnh gọi hàm này rất nhanh.

Ngược lại của ràng buộc sớm là ràng buộc muộn. Liên kết muộn đề cập đến các lệnh gọi hàm không được giải quyết cho đến thời gian chạy. Các chức năng ảo được sử dụng để đạt được ràng buộc muộn. Như bạn đã biết, khi truy cập thông qua con trỏ cơ sở hoặc tham chiếu, hàm ảo thực sự được gọi được xác định bởi kiểu đối tượng được con trỏ trỏ tới. Bởi vì trong hầu hết các trường hợp, điều này không thể được xác định tại thời điểm biên dịch, đối tượng và hàm không được liên kết cho đến thời gian chạy. Ưu điểm chính của ràng buộc muộn là tính linh hoạt. Không giống như ràng buộc sớm, ràng buộc muộn cho phép bạn tạo các chương trình có thể đáp ứng các sự kiện xảy ra trong khi chương trình thực thi mà không cần phải tạo một lượng lớn "mã dự phòng". Hãy nhớ rằng vì một lệnh gọi hàm không được giải quyết cho đến thời gian chạy, liên kết trễ có thể làm cho thời gian thực thi chậm hơn một chút. Tuy nhiên ngày nay,


1
"đối tượng và hàm không được liên kết cho đến khi thời gian chạy" Câu lệnh này dường như ngụ ý rằng một đối tượng tồn tại trước thời gian chạy. Không phải các đối tượng hoàn toàn chạy các thực thể thời gian? Nó là lớp của đối tượng tồn tại tại thời điểm biên dịch. Điều này có thể được trình bày tốt hơn là "cuộc gọi chức năng và thực hiện nó không liên quan đến thời gian chạy"
programmerravi

một ví dụ về liên kết trễ là trong đa hình (trong OOP) mà chúng ta sử dụng các giao diện hoặc các lớp trừu tượng và sau đó chúng ta liên kết với nó trong thời gian chạy.
Mohamad Mirzadeh

3

Trong các ngôn ngữ thông dịch, sự khác biệt nhỏ hơn một chút.

Ruby:

# early binding:
def create_a_foo(*args)
  Foo.new(*args)
end
my_foo = create_a_foo

# late binding:
def create_something(klass, *args)
  klass.new(*args)
end
my_foo = create_something(Foo)

Bởi vì Ruby (nói chung) không được biên dịch nên không có trình biên dịch để thực hiện những thứ tiện lợi. Sự phát triển của JRuby có nghĩa là ngày nay, ngày càng có nhiều Ruby được biên dịch, khiến nó hoạt động giống Java hơn.

Vấn đề với IDE vẫn còn tồn tại: một nền tảng như Eclipse có thể tra cứu các định nghĩa lớp nếu bạn mã hóa chúng, nhưng không thể nếu bạn để chúng cho người gọi.

Inversion-of-control không quá phổ biến trong Ruby, có thể là do tính linh hoạt trong thời gian chạy của nó, nhưng Rails tận dụng rất tốt tính năng liên kết muộn để giảm lượng cấu hình cần thiết để ứng dụng của bạn hoạt động.


Điểm này cũng áp dụng cho các ngôn ngữ đã biên dịch có thể bao gồm các thành phần JIT được biên dịch và được đưa vào thời gian chạy để triển khai các plugin hoặc khung động. Một số ví dụ kinh điển về điều này tồn tại trong Java, và tất nhiên là cả Ruby và Python. Một ví dụ điển hình là Erlang, nơi thời gian chạy có thể tải hai phiên bản của bất kỳ mô-đun nào cùng một lúc để nâng cấp / hạ cấp trực tiếp. Vì vậy, mặc dù rất nhiều mã Erlang (hầu hết?) Được viết dưới dạng các hàm thuần túy được nhập tĩnh, các yêu cầu thời gian chạy bắt buộc các loại ràng buộc muộn và động nằm dưới mui xe.
zxq9

0
public class child()
{    public void method1()
     {     System.out.println("child1");
     }
    public void method2()
     {     System.out.println("child2");
     }

}
public class teenager extends child()
{    public void method3()
     {      System.out.println("teenager3");
     }
}
public class adult extends teenager()
{     
    public void method1()
    {    System.out.println("adult1);
         super.method1();
     }
}


//In java
public static void main(String []args)
{    ((teenager)var).method1();
}

Điều này sẽ in ra

adult1
child1

Trong liên kết sớm, trình biên dịch sẽ có quyền truy cập vào tất cả các phương thức ở trẻ em và thanh thiếu niên nhưng trong ràng buộc muộn (trong thời gian chạy), nó sẽ kiểm tra các phương thức bị ghi đè trong thời gian chạy.

Do đó method1 (từ con - ràng buộc sớm) sẽ bị ghi đè bởi method1 từ người lớn trong thời gian chạy (ràng buộc muộn) Sau đó, nó sẽ triển khai method1 từ child vì không có method1 trong method1 ở thanh thiếu niên.

Lưu ý rằng nếu con không có method1 thì mã trong main sẽ không được biên dịch.


0

Tính đa hình thời gian biên dịch còn được gọi là quá tải hoặc liên kết sớm hoặc liên kết tĩnh khi chúng ta có cùng tên phương thức với các hành vi khác nhau. Bằng cách triển khai nhiều nguyên mẫu của cùng một phương pháp và các hành vi khác nhau xảy ra trong đó. Ràng buộc sớm đề cập đến việc biên dịch đầu tiên của chương trình. Nhưng trong đối tượng ràng buộc muộn là thời gian chạy xảy ra trong chương trình. Còn được gọi là Liên kết động hoặc ghi đè hoặc Đa hình thời gian chạy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.