2010-07-11 33 views
12

Tôi biết một vài quy tắc liên quan đến loại Objective-C:Điều gì xảy ra nếu hai danh mục ObjC ghi đè lên cùng một phương pháp?

  1. loại phương pháp không nên ghi đè lên các phương pháp hiện có (lớp hoặc chẳng hạn)
  2. Hai khác nhau loại thực hiện cùng một phương pháp cho cùng lớp sẽ dẫn đến hành vi undefined

tôi muốn biết những gì xảy ra khi tôi ghi đè lên một trong những phương pháp loại của riêng tôi trong t anh ấy cùng loại. Ví dụ:

@interface NSView (MyExtensions) 
- (void)foo; // NSView category implementation 
@end 

@interface MyClass : NSView 
{ } 
@end 

@interface MyClass (MyExtensions) 
- (void)foo; // MyClass category implementation 
@end 

Với các giao diện này được xác định, phương pháp nào sẽ được thực thi khi tôi chạy mã sau?

MyClass * instance = [[MyClass alloc] initWith...]; 
[instance foo]; 
[instance release]; 

Lưu ý: Với trình biên dịch của tôi, việc triển khai MyClass được ưu tiên, nhưng tôi không chắc chắn nếu điều đó được đảm bảo hay chỉ một hương vị cụ thể của hành vi không xác định.

Trả lời

12

Mỗi phương pháp của mỗi lớp đều có triển khai. Một danh mục sẽ thêm hoặc thay thế một phương thức cho một lớp cụ thể. Điều đó có nghĩa là hành vi bạn đang thấy, trong đó MyClass có một foo và NSView có một số khác là foo, được xác định rõ. Bất kỳ trường hợp nào của MyClass sẽ có foo khác với bất kỳ phiên bản nào của NSView không phải là MyClass, giống như foo đã được xác định trong quá trình triển khai chính và không phải là danh mục. Bạn thậm chí có thể gọi số [super foo] từ MyClass để truy cập vào số foo được xác định cho NSView.

+3

Có đúng để ghi đè trong phương pháp Danh mục được khai báo và triển khai trong Danh mục siêu lớp không? – BergP

32

Để mở rộng câu trả lời rút ra:

Đó là vấn đề về phân cấp. Danh mục thực sự chỉ là phương tiện tổ chức các tệp nguồn. Khi được biên dịch, tất cả các phương thức của một lớp, bao gồm các phương thức được định nghĩa trong bất kỳ thể loại nào, kết thúc trong cùng một tệp.

Mọi thứ bạn có thể làm trong giao diện lớp thông thường bạn có thể làm trong danh mục và bất kỳ thứ gì bạn không nên làm trong giao diện lớp thông thường mà bạn không nên làm trong danh mục.

Vì vậy:

loại phương pháp không nên ghi đè phương pháp hiện có (lớp hoặc trường hợp)

Bạn có thể sử dụng phương pháp định nghĩa trong giao diện lớp thường xuyên để ghi đè thừa hưởng phương pháp để bạn có thể ghi đè các phương thức được kế thừa trong một danh mục. Tuy nhiên, bạn sẽ không bao giờ cố gắng có hai định nghĩa phương thức giống hệt nhau trong cùng một giao diện bình thường, do đó bạn sẽ không bao giờ có một phương thức trong một danh mục có cùng tên như một phương thức trong giao diện thông thường hoặc một danh mục khác trên giao diện thông thường. cùng lớp. Vì tất cả các định nghĩa phương thức kết thúc trong cùng một tệp được biên dịch, chúng rõ ràng sẽ va chạm.

Hai loại khác nhau thực hiện kết quả phương pháp tương tự trong hành vi undefined

Điều đó sẽ được viết lại để nói "Hai loại khác nhau thực hiện cùng một phương pháp cho lớp cùng kết quả trong không xác định hành vi." Một lần nữa, bởi vì tất cả các phương thức cho bất kỳ một lớp nào kết thúc trong cùng một tệp, có hai phương thức trong cùng một lớp rõ ràng sẽ gây ra sự kỳ quặc.

Bạn có thể sử dụng các danh mục để cung cấp các phương thức ghi đè các phương thức siêu lớp vì lớp và lớp cha của nó là hai lớp riêng biệt.

Nếu bạn từng bối rối về việc liệu danh mục có gây ra vấn đề hay không, hãy tự hỏi mình: "Các phương pháp trong danh mục có hoạt động không nếu tôi sao chép và dán tất cả vào tệp'h/.m 'của lớp?" Nếu câu trả lời là "có" thì bạn đã rõ ràng. Nếu "không", sau đó bạn đã có vấn đề.

+2

+1 Cảm ơn bạn. Đó là một cách rất hay để mô tả nó. Tôi cũng đã thay đổi từ ngữ trên quy tắc số 2 để phù hợp với bạn. –

Các vấn đề liên quan