Ghi đè các phương pháp sử dụng các danh mục trong Objective-C


87

Tôi có thể sử dụng một thể loại lớp để ghi đè một phương thức đã được triển khai bằng một thể loại không? Như thế này:

1) Phương pháp ban đầu

-(BOOL) method {
  return true;
}

2) Phương pháp ghi đè

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Điều này sẽ hoạt động, hay điều này là bất hợp pháp?

Câu trả lời:


146

Từ tài liệu của Apple :

Mặc dù ngôn ngữ Objective-C hiện cho phép bạn sử dụng một thể loại để ghi đè các phương thức mà lớp kế thừa, hoặc thậm chí các phương thức được khai báo trong giao diện lớp, bạn thực sự không khuyến khích làm như vậy . Một thể loại không thay thế cho một lớp con. Có một số thiếu sót đáng kể khi sử dụng danh mục để ghi đè các phương pháp:

  • Khi một danh mục ghi đè một phương thức kế thừa, phương thức trong danh mục, như thường lệ, có thể gọi triển khai kế thừa thông qua một thông báo tới super. Tuy nhiên, nếu một danh mục ghi đè một phương thức tồn tại trong lớp của danh mục, thì không có cách nào để gọi triển khai ban đầu .

  • Một danh mục không thể ghi đè lên các phương thức được khai báo trong một danh mục khác của cùng một lớp một cách đáng tin cậy.

    Vấn đề này có ý nghĩa đặc biệt vì nhiều lớp Cacao được thực hiện bằng cách sử dụng các danh mục. Một phương thức do khuôn khổ xác định mà bạn cố gắng ghi đè có thể đã được triển khai trong một danh mục và do đó việc triển khai nào được ưu tiên không được xác định.

  • Sự hiện diện của một số phương thức danh mục có thể gây ra thay đổi hành vi trên tất cả các khuôn khổ. Ví dụ: nếu bạn ghi đè windowWillClose:phương thức ủy nhiệm trong một danh mục trên NSObject, thì tất cả các đại biểu cửa sổ trong chương trình của bạn sẽ phản hồi bằng phương pháp danh mục; hành vi của tất cả các phiên bản NSWindow của bạn có thể thay đổi. Các danh mục bạn thêm vào một lớp khung có thể gây ra những thay đổi bí ẩn trong hành vi và dẫn đến sự cố.


Cảm ơn bạn nhưng tôi đã biết điều đó. Tôi chỉ băn khoăn rằng trường hợp của tôi có hợp pháp hay không. Trường hợp của tôi có một chút khác biệt so với các tài liệu. :)
retix

Tại sao nó khác nhau? Tài liệu nói rằng nó là hợp pháp NẾU phương pháp gốc không nằm trong danh mục, nhưng rất không được khuyến khích. Sau đó, bạn có thể làm điều đó ...
Benoît

1
Cám ơn về lời khuyên của bạn. Tôi kém ngôn ngữ này. Tôi nhận được thông tin mới từ bạn.
retix

1
Việc ghi đè trong phương thức Category được khai báo và thực hiện trong Category của siêu lớp có đúng không?
BergP

2
Liên kết bị hỏng, đây có phải là phiên bản mới? developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
RndmTsk


9

Liên kết tài liệu cũ đã chết; thay thế tốt nhất mà tôi có thể tìm thấy ở đây: Apple Docs :

Tránh xung đột tên phương pháp danh mục

Vì các phương thức được khai báo trong một danh mục được thêm vào một lớp hiện có, bạn cần phải rất cẩn thận về tên phương thức.

Nếu tên của một phương thức được khai báo trong một danh mục giống với một phương thức trong lớp ban đầu hoặc một phương thức trong một danh mục khác trên cùng một lớp (hoặc thậm chí là một lớp cha), thì hành vi không được xác định về việc triển khai phương thức nào được sử dụng tại thời gian chạy. Điều này ít có khả năng xảy ra nếu bạn đang sử dụng các danh mục với các lớp của riêng mình, nhưng có thể gây ra sự cố khi sử dụng các danh mục để thêm các phương thức vào các lớp Ca cao hoặc Cảm ứng Ca cao tiêu chuẩn.

Đó là Apple sử dụng một cú chạm nhẹ hơn, nhưng điểm chính giống nhau: bạn dẫn đến thảm họa, bởi vì hành vi không thể đoán trước là im lặng.


2

Điều quan trọng cần lưu ý là một thể loại cũng có thể được sử dụng để ghi đè các phương thức hiện có trong lớp cơ sở (ví dụ: phương thức ổ đĩa của lớp Xe), nhưng bạn không bao giờ nên làm điều này. Vấn đề là các danh mục là một cơ cấu tổ chức phẳng. Nếu bạn ghi đè một phương thức hiện có trong Car + Maintenance.m và sau đó quyết định muốn thay đổi lại hành vi của nó bằng một danh mục khác, thì không có cách nào để Objective-C biết nên sử dụng triển khai nào. Phân lớp hầu như luôn là một lựa chọn tốt hơn trong tình huống như vậy.

Từ hướng dẫn này, http://rypress.com/tutorials/objective-c/categories

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.