2010-09-22 27 views
16

Tôi muốn đặt đại biểu của một đối tượng bên trong một phương thức lớp trong Objective-C. Mã giả:Mục tiêu-C tương đương với các lớp ẩn danh của Java trong các phương thức lớp

+ (ClassWithDelegate*) myStaticMethod { 
    if (myObject == nil) { 
     myObject = [[ClassWithDelegate alloc] init]; 
     // myObject.delegate = ? 
    } 
    return myObject; 
} 

Trong Java, tôi chỉ cần tạo một lớp ẩn danh đã triển khai giao thức đại biểu. Làm thế nào tôi có thể làm điều gì đó tương tự trong Objective-C?

Về cơ bản tôi muốn tránh tạo một lớp (và tệp) riêng biệt để triển khai giao thức đại biểu đơn giản.

+0

thể trùng lặp của [? Anonymous thực hiện ủy nhiệm trong Objective-C] (http://stackoverflow.com/questions/766475/anonymous-delegate-implementation-in- Mục tiêu-c) –

+0

@Dave DeLong Làm rõ tiêu đề để phân biệt với câu hỏi đó. Trong trường hợp này ngữ cảnh là một phương thức tĩnh. – hpique

+0

ngữ cảnh không quan trọng. Bạn phải cung cấp một đối tượng ('id') làm đại biểu, và câu hỏi khác khá rõ ràng trả lời rằng không có thứ như một lớp ẩn danh trong Objective-C (chưa), vì vậy bạn sẽ phải sử dụng một đối tượng bình thường. –

Trả lời

13

Hiện tại không có lớp ẩn danh nào trong Mục tiêu-C.

Thường thì bạn có thể sử dụng đối tượng đã tồn tại. Ví dụ, đối với một NSTableViewDataSource, bạn có thể thực hiện các phương thức trong bộ điều khiển tài liệu hoặc xem và chuyển giao nó như là người đại diện.

Hoặc bạn có thể có đối tượng tự thực hiện giao thức và đặt làm đại biểu riêng trong trường hợp mặc định.

Hoặc các phương thức gửi tin nhắn đại biểu có thể kiểm tra một đại biểu nil và làm điều gì đó hợp lý trong tình huống đó.

Hoặc bạn có thể khai báo và xác định một lớp bên trong tệp triển khai mà bạn đang tạo đối tượng cần một đại biểu.

+0

Cảm ơn JeremyP! Vì vậy, về cơ bản trong trường hợp này tôi có thể định nghĩa một lớp ad-hoc trong tệp thực hiện, tạo một cá thể trong thông điệp lớp và gán nó làm đại biểu. Điều đó có đúng không? – hpique

+0

Đó có lẽ là cách phù hợp để thực hiện điều đó trong tình huống này. – JeremyP

16

Như JeremyP đã nói đúng, Không có lớp ẩn danh nào trong Mục tiêu C như có trong Java.

Nhưng trong Java, các lớp ẩn danh chủ yếu được sử dụng để triển khai giao diện phương thức đơn hoặc những gì chúng tôi cũng gọi là giao diện chức năng .

Chúng tôi làm điều đó để tránh phải thực hiện các giao diện trong một lớp học chỉ dành riêng cho một phương pháp thực hiện mà thường được sử dụng cho Listeners, quan sát và xử lý sự kiện.

Điều này chủ yếu là do thiếu chức năng lớp ẩn danh đầu tiên trong Java (trước phiên bản 8 và dự án lambda).

Objective C có cái gì gọi là khối, nơi bạn có thể trực tiếp thông qua một khối, trong đó có việc thực hiện các phương pháp đơn chứ không phải là một lớp học trống quấn nó lên.

Ví dụ:

Một ứng dụng của Anonymous Class trong Java

//Functional interface 
interface SomethingHandler 
{ 
    void handle(Object argument); 
} 

//a method that accepts the handler in some other class 
class SomeOtherClass 
{ 
    void doSomethingWithCompletionHandler(SomethingHandler h){ 
     // do the work that may consume some time in a separate thread may be. 
     // when work is done call the handler with the result which could be any object 
     h.handler(result); 
    }; 
} 

// Somewhere else in some other class, in some other code 
// passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed 
SomeOtherClass someObj = new SomeOtherClass(); 
someObj.doSomethingWithCompletionHandler(new SomethingHandler() 
         { 
           void handle(Object argument) 
           { 
           // handle the event using the argument 
           } 
         }); 

Trong Objective C

// declare the handler block 
typedef void (^SomethingHandler)(id argument){} 

// this interface is different than Java interface which are similar to Protocols 
@interface SomeOtherClass 
-(void)doSomethingWithCompletionHandler:(SomethingHandler)h; 
@end 

@implementation SomeOtherClass 
-(void)doSomethingWithCompletionHandler:(SomethingHandler)h 
{ 
      // do the work that may consume some time in a separate thread may be. 
      // when work is done call the handler with the result which could be any object 
      h(result); 
} 

@end 

    // passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed 

SomeOtherClass* someObj = [[SomeOtherClass alloc] init]; // ARC :) 

[someObj doSomethingWithCompletionHandler:^(id argument) 
              { 
               // handle the event using the argument 
              }]; 
1

lớp Anonymous có thể được thực hiện với thư viện.Một vài tháng trước, tôi đã làm việc trên MMMutableMethods ngã ba để cải thiện việc thực hiện cũ (thảo luận với tác giả) và thêm cơ chế của riêng tôi mà không cần bất kỳ thao tác thời gian chạy obj-c nào.

https://github.com/k06a/MMMutableMethods

A. cơ chế đầu tiên hoạt động trên obj-c runtime tạo lớp:

MM_CREATE(MM_REUSE,^(Class class){ 
    [class addMethod:@selector(onResultWithId:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,id res){ 
       NSLog(@"onResultWithId: %@",res); 
      }]; 
    [class addMethod:@selector(onErrorWithJavaLangException:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,JavaLangException *e){ 
       NSLog(@"onErrorWithJavaLangException: %@",e); 
      }]; 
}) 
cơ chế

B. Thứ hai hoạt động trên thông điệp đơn giản chuyển tiếp thực hiện:

MM_ANON(^(MMAnonymousClass *anon){ 
    [anon addMethod:@selector(onResultWithId:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,id res){ 
       NSLog(@"onResultWithId: %@",res); 
      }]; 
    [anon addMethod:@selector(onErrorWithJavaLangException:) 
     fromProtocol:@protocol(AMCommandCallback) 
      blockImp:^(id this,JavaLangException *e){ 
       NSLog(@"onErrorWithJavaLangException: %@",e); 
      }]; 
}) 

Đầu tiên tạo các lớp obc-j mới trong thời gian chạy, nó cho phép bạn tạo các lớp MM_CREATE_CLASS(MM_REUSE, *) và các cá thể trực tiếp với MM_CREATE(MM_REUSE, *). Các lớp học sẽ chỉ được tạo khi thực hiện lần đầu và được sử dụng lại theo mặc định, nhưng bạn có thể tránh sử dụng lại bằng cách gọi MM_CREATE_CLASS_ALWAYS(*)MM_CREATE_ALWAYS(*).

Cơ chế thứ hai không tạo ra bất kỳ phiên bản thời gian chạy nào, chỉ cần nhớ các khối cho bộ chọn và các cuộc gọi phương thức chuyển tiếp đến chúng.

Tôi làm theo cách thứ hai để không tạo nhiều lớp trong thời gian chạy. IMHO nó an toàn hơn và đủ mạnh mẽ.

Để sử dụng thư viện này chỉ:

pod 'MMMutableMethods', :git => 'https://github.com/k06a/MMMutableMethods' 
Các vấn đề liên quan