2013-04-12 25 views
5

Mỗi lớp xem có nhiều phương thức init - các lớp đã được bao gồm như một phần của UIView, và sau đó là các phương thức bổ sung - và mỗi phương thức đều thiết lập các phần tử giống nhau theo cùng một cách. Do đó, tôi thường có tất cả chúng chạy phương thức [self initialSetup];, bao gồm việc thiết lập tất cả các phần tử này. Vấn đề tôi đã gặp phải là nếu một lớp con cũng có một phương thức initialSetup, nó sẽ ghi đè lên phương thức initialclass initialSetup, và do đó lớp cha sẽ phải có phương thức công khai để vẫn hoạt động. Điều này gây ra vấn đề với tổ chức, vì phương pháp không bao giờ nên được gọi là khác với init, do đó không có lý do để được công khai.Cách tốt nhất để thực hiện init mà không cần lặp lại mã?

Trả lời

2

Bạn đã gặp sự cố không có sửa chữa hoàn hảo. Điều bạn lý tưởng có là một phương thức không thể được phân lớp theo nghĩa thông thường, nó chỉ có thể truy cập được đối với các thể hiện của kiểu lớp chính xác đó.

Trường hợp đây là rủi ro, thực tiễn thông thường dường như là kết hợp tên lớp vào phương pháp thiết lập. Vì vậy, thay vì initialSetup, bạn sẽ có một cái gì đó như myViewSubclassInitialSetup.

Bạn cũng có thể thêm một cái gì đó như thế này ở phía trên cùng của phương pháp của bạn:

NSAssert([self isMemberOfClass:[ThisClass class]], 
      @"IniitalSetup called by sub- or superclass") 

Sau đó, gỡ lỗi của bạn xây dựng sẽ nâng cao một ngoại lệ nếu một lớp con hoặc cha kết thúc lên gọi phương thức init của bạn. Điều đó sẽ cung cấp cho bạn một nơi cho một breakpoint và một stacktrace mà sẽ cho phép bạn tìm thấy vấn đề rất nhanh chóng.

Nó sẽ không thêm bất kỳ mã nào vào bản phát hành bản phát hành của bạn.

2

Thay đổi tên của initialSetup thành một cái gì đó như initialSetupClassName - các lớp con, ngay cả khi chúng vô tình sử dụng cùng một mẫu, sẽ không sử dụng cùng tên khi chúng có tên lớp khác.

Bạn cũng có thể sử dụng tiền tố "_" cho các phương thức riêng tư mà bạn không muốn được gọi, nhưng subclasser cũng có thể thực hiện điều đó.

1

Unfortunatly Objective C không cung cấp cách để đạt được điều đó theo cách "sạch". Giải pháp lý tưởng sẽ là một phương pháp được bảo vệ. Nhưng điều đó không thể xảy ra trong Objective C

Apple gặp sự cố này khi họ tạo UIGestureRecognizer. Có một số phương pháp họ thực sự không muốn bị gọi bởi ai đó, nhưng phải được ghi đè bởi các lớp con. Cách họ chọn để đối phó với điều này, là tạo ra một tập tin tiêu đề riêng biệt (UIGestureRecognizerSubclass.h), có chứa một thể loại để ban đầu UIGestureRecognizer với những phương pháp "được bảo vệ". Tiêu đề bổ sung chỉ được nhập bởi các lớp con (tức là cho các mục đích phân lớp). Xem UIGestureRecognizer Class Reference để biết một số chi tiết.

Tất nhiên điều đó không ngăn cản bất kỳ ai lạm dụng tệp tiêu đề bổ sung, nhưng ít nhất nó nêu rõ ý định của bạn và giữ cho mã của bạn được cấu trúc tốt. Ngoài ra, bạn sẽ không bị "làm phiền" bởi tự động hoàn thành cho các phương thức bổ sung, khi chỉ sử dụng lớp.

Cá nhân tôi chỉ sử dụng tiêu đề bổ sung, nếu điều cực kỳ quan trọng là không ai gọi trực tiếp. Trong hầu hết các trường hợp, tôi nghĩ rằng đó là ok để sử dụng phương pháp công cộng và làm cho một lưu ý cho những gì nó inteded. Khuôn khổ iOS cũng có nhiều trường hợp này. F.e. nhiều phương thức của UIViewController 's viewDidLoad vv.

2

Có vẻ như bạn đang thiếu một bộ khởi tạo được chỉ định.Chỉ định một trình khởi tạo làm trình khởi tạo chính thức thực sự thiết lập và có tất cả những người khác chỉ cần gọi với một mức độ tùy chỉnh nào đó. Thông thường, trình khởi tạo được chỉ định sẽ là bộ tạo chi tiết nhất - ví dụ: nếu bạn có init, initWithName:, initWithName:age:initAsFiveYearOldNamed:, trình khởi tạo được chỉ định sẽ là initWithName:age: và các trình khởi tạo khác sẽ gọi phương thức đó với các đối số được điền một cách thích hợp.

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