2010-02-02 16 views
8

Có thể tạo lớp không có phương thức init để buộc tất cả người gọi tạo đối tượng bằng phương pháp nhà máy thay thế không?Tạo một lớp không có phương thức init (Mục tiêu-c)

+1

Có thể hữu ích khi giải thích những gì bạn thực sự muốn thực hiện. – Chuck

+1

Dường như là một câu hỏi hoàn toàn hợp pháp đối với tôi, điều đó không cần bối cảnh để có ý nghĩa. Có rất nhiều lý do tại sao bạn sẽ có một lớp học mà sẽ không cần bất kỳ thiết lập cụ thể. –

+0

@Squeegy: Chuck đã đúng - câu hỏi ban đầu nên giải thích những gì tôi muốn thực hiện. Từ những câu trả lời dưới đây, rõ ràng một số người trả lời không chắc tôi đang hỏi gì (tôi thực sự đã bình chọn bình luận của Chuck) – Casebash

Trả lời

5

Vì vậy, về cơ bản, bạn muốn đảm bảo rằng lớp học của bạn không bao giờ được khởi tạo bằng -init, phải không? Bạn không thể làm chính xác những gì bạn muốn làm, nhưng bạn có thể đến gần.

Vì bạn kế thừa từ NSObject, bạn có phương thức init và bạn không thể làm gì để ngăn không cho nó được gọi.Điều đó nói rằng, bạn có thể ghi đè lên init này:

- (id)init 
{ 
    [self dealloc]; 
    @throw [NSException exceptionWithName:@"MyExceptionName" reason:@"Reason" userInfo:nil]; 
    return nil; 
} 

Bằng cách này, bất cứ lúc nào có ai đó gọi phương pháp init của bạn, nó cũng giết đối tượng, vì vậy nói thực tế, phương pháp init của bạn là khá nhiều un-callable.

+0

Mục tiêu-c có cái gì đó giống như một ngoại lệ không được thực hiện? – Casebash

+0

Bạn thực sự không cần trả lại ở cuối - nó sẽ không bao giờ đạt được – Casebash

+1

Mục tiêu-C là ngoại lệ-không thân thiện vì nó có thể khiến các đối tượng bị rò rỉ khắp nơi (vì các lệnh gọi 'release' của họ không bao giờ có thể đạt được) . Nếu bạn không sử dụng thời gian chạy được thu gom rác, tuy nhiên bạn có thể buồn, nhưng tốt hơn là bạn không nên sử dụng chúng. – zneak

0

Chắc chắn. Trong Mục tiêu-C, không có các nhà thầu thực tế . init phương pháp kiểu thường được sử dụng để khởi tạo một lớp, trong cùng một tĩnh mạch như một hàm tạo, nhưng chúng chỉ là một phương thức "bình thường" (không có gì đặc biệt về chúng như có, ví dụ, Java constructors).

Điều đó nói rằng, trừ khi lớp học của bạn không không khởi cho trường hợp của mình, bạn có thể muốn để có một số loại init phương pháp.

0

NSObject triển khai phương thức init cho bạn thực hiện bất kỳ thao tác nào. Nếu lớp của bạn không có gì để thiết lập khi nó được khởi tạo thì chỉ cần không ghi đè phương thức -(id)init được cung cấp bởi NSObject. Nhưng bạn vẫn gọi nó khi bạn tạo cá thể.

1

Tùy thuộc. Nếu bạn có lớp của bạn được kế thừa từ NSObject, nó sẽ có phương thức init được kế thừa (không làm gì với các biến đối tượng của bạn). Vì vậy, trong ý nghĩa đó, ngay cả khi bạn thực sự thực sự muốn không có phương thức init, bạn vẫn có thể có một phương pháp. Vì vậy, nếu câu hỏi của bạn là "Tôi có cần triển khai phương pháp init tầm thường không?", Câu trả lời là "không, bạn không cần phải". Tuy nhiên, nếu câu hỏi của bạn là "Tôi có cần gọi phương thức init nếu tôi không ghi đè nó không?", Thì câu trả lời là "có, bạn làm". Dù bạn làm gì với lớp con NSObject, tại một số điểm bạn vẫn cần gọi init sau khi đối tượng được tạo. Đó là cách sống.

Điều đó đang được nói, bạn nhiều khả năng là muốn có phương thức init, trừ khi khởi tạo đối tượng của bạn không yêu cầu gì khác hơn là lấy toàn bộ đối tượng của bạn.

Ngược lại, nếu bạn chọn để không kế thừa từ NSObject hoặc bất kỳ lớp con của nó và chỉ cần kế thừa từ không có gì, mà rõ ràng là một ý tưởng tồi vì cách NSObject giao lớp học với tất cả những gì runtime ObjC cần làm và yêu cầu khá cao, sau đó bạn sẽ có khả năng kết thúc với phương thức initở tất cả. Nhưng nghiêm túc, đừng thử ở nhà.

4

Nếu bạn thực sự muốn gây rắc rối cho người dùng của lớp người sử dụng init, bạn có thể làm:

@implementation MyClass 

- (id) init 
{ 
    // Still have to make sure the runtime has initialised everything for "self" 
    self = [super init]; 
    if (!self) return nil; 
    [self release]; // some say you should use [super dealloc] 
    [super doesNotRecognizeSelector:_cmd]; 
    return nil; 
} 

@end 

Bạn có thể gọi super 's doesNotRecognizeSelector: bởi vì bạn có thể muốn thực hiện hành vi của riêng bạn cho selectors không được công nhận cho lớp của bạn.

+0

Tại sao chúng ta không thể trở lại nil? – Casebash

+0

Ồ, nếu nó được phân bổ, chúng tôi sẽ giải phóng – Casebash

+0

Bạn chỉ có thể trả lại không, và đó có lẽ là lựa chọn tốt hơn ở đây. – Chuck

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