2012-01-25 8 views
7

Tôi có một ứng dụng mà tôi đang viết chỉ sử dụng @properties. Tôi không có một thanh cương nào được khai báo trong bất kỳ tập tin lớp nào của tôi. Theo tôi hiểu nó ivars không còn cần thiết với sự ra đời của @property. Tôi có mã hóa theo thực tiễn tốt nhất không? Điều này sẽ kết thúc cắn tôi trong mông ngôn ngữ trong dài hạn? Tôi đã đọc các bài đánh giá hỗn hợp về nội dung "đúng" và "sai" ...Tôi có nên sử dụng ivars trong Objective-C không?

+0

Lưu ý rằng nếu bạn có cả khai báo ivar và khai báo thuộc tính cho cùng một mã vạch, mã của bạn không phải là DRY (không lặp lại chính mình). –

+0

Câu trả lời cho câu hỏi này phụ thuộc, trong số những thứ khác, khi bạn đặt câu hỏi. Cách tiếp cận "lý tưởng" ở đây là một mục tiêu chuyển động. –

Trả lời

11

Tôi thường không khai báo ivars. Tôi sẽ thường sử dụng @synthesize foo = foo_; mặc dù để ngăn chặn truy cập trực tiếp khi tôi có nghĩa là thông qua phương pháp hoặc ngược lại. Và tôi luôn để trình biên dịch tự động tổng hợp ngà với tiền tố _ (ngăn chặn truy cập trực tiếp tình cờ, theo số xảy ra cụm từ ). Và, như Caleb đã nói, vẫn còn những vệt nổi, bạn chỉ cần không tuyên bố rõ ràng trừ khi bạn thực sự muốn (mà, thực sự, bạn không làm ngà voi trong tiêu đề không hữu ích đối với khách hàng của lớp học, nếu API của bạn được thiết kế phù hợp).

Tôi cũng thấy rằng quảng cáo trên "chỉ sử dụng truy cập trực tiếp trong init/dealloc, sử dụng setter/getter ở mọi nơi khác" để phần lớn bị thổi phồng và do đó, chỉ cần sử dụng setter/getter ở khắp mọi nơi. Thực tế là nếu bạn có quan sát viên trong quá trình khởi tạo/deallocation, bạn đã được hosed; trạng thái của đối tượng, theo định nghĩa, không xác định trong quá trình xây dựng/hủy diệt và do đó, một người quan sát không thể có lý do chính xác về trạng thái.


Như Caleb chỉ ra, một lý do khác để sử dụng truy cập Ivar trực tiếp trong init/dealloc là để tránh các lớp con mà thực hiện tùy chỉnh Logic setter/getter có thể barf do tình trạng không xác định của đối tượng trong init/dealloc.

Trong khi điều này có thể đúng, tôi coi đó là một lỗ hổng kiến ​​trúc khó chịu để thực hiện các bộ định cư/getters với hành vi tùy chỉnh. Làm như vậy là mong manh và làm cho nó khó khăn hơn để cấu trúc lại mã theo thời gian. Đồng thời, hành vi tùy chỉnh như vậy thường sẽ có sự phụ thuộc vào trạng thái khác trong đối tượng và sự phụ thuộc đó sau đó dẫn đến sự phụ thuộc thứ tự về các thay đổi trạng thái không được phản ánh bởi khai báo đơn giản dường như đơn giản @property.

I.e. nếu người định cư và getters của bạn được viết sao cho không thể thực hiện foo.bar = bad; tại bất kỳ thời gian nào trên foo, thì mã của bạn bị vỡ.

+1

Tôi thấy rằng nếu tôi không khai báo rõ ràng ivars, tôi không thể kiểm tra giá trị của chúng trong trình gỡ lỗi. Vì vậy, tôi đã thực hiện thói quen tuyên bố rõ ràng ivars cho các loại giá trị. –

+0

@ohhorob Họ nói điều đó ở đâu? Không phải là tôi không đồng ý - tôi luôn nghĩ đó là trường hợp. Nhưng tôi đã tìm kiếm một tuyên bố cho hiệu ứng đó trong các tài liệu một vài lần gần đây và xuất hiện trống rỗng. Nếu bạn tình cờ biết nó ở đâu, hãy chia sẻ! – Caleb

+0

@Emile - Ahhh! Đó là điều tuyệt vời để biết. Tôi đã luôn luôn tự hỏi tại sao trong một số ứng dụng tôi có thể thấy giá trị trong trình gỡ lỗi và đôi khi không. Có lẽ IS này gắn liền với việc có hay không một ivar được khai báo. Tôi phải điều tra điều này ngay lập tức! =) – ElasticThoughts

2

Sử dụng iVars chắc chắn không sai, tuy nhiên các phương pháp hay nhất hiện đang đẩy để sử dụng @property.

15

Không cần quá nhiều biến mẫu. Nó chỉ là biến số biến thể không cần thiết. Với một thuộc tính và một câu lệnh @synthesize, trình biên dịch sẽ xử lý việc tạo biến cá thể cùng với các phương thức accessor thích hợp.

Không có gì sai khi chỉ sử dụng các thuộc tính. Chúng đơn giản hóa việc quản lý bộ nhớ. Cũng không có gì sai khi sử dụng iVars mà không có thuộc tính, nếu đó là những gì bạn muốn. Nếu bạn muốn sử dụng thuộc tính nhưng không muốn quảng cáo người truy cập vào phần còn lại của thế giới (nghĩa là duy trì đóng gói), hãy xem xét tuyên bố thuộc tính không công khai của bạn trong tiện ích mở rộng lớp (về cơ bản là danh mục ẩn danh trong tệp triển khai của bạn).

0

Một nơi bạn có thể muốn sử dụng thanh ngang là khi bạn muốn khai báo thuộc tính được bảo vệ. Bạn khai báo thuộc tính trong tệp .m cho một lớp và khai báo ivar tương ứng của nó trong .h với chỉ thị @protected.Điều này sau đó sẽ cho phép bạn có quyền truy cập được bảo vệ trong lớp con. Không có cách nào khác để bảo vệ quyền truy cập vào các thành viên.