随着蘋果将預設的編譯器從gcc換成了llvm,編譯器自動為一個屬性生成對應的變量和setter/getter方法,我們已經越來越習慣在自己建立的類中直接通過聲明一個屬性來建立一個類變量了。比如:
但是卻忽視了屬性和變量本質上的差別,導緻在使用中遇到很多奇怪的問題無法了解,尤其是在非arc下這種情況就更是如此。
在最早的ios程式設計中,我們必須為每一個屬性聲明一個對應的變量,兩者互相配合使用,比如:
但是現在我們并不需要這麼寫,隻需要聲明一個屬性比如name,那麼編譯器就會自動為其聲明一個對應的變量_name。在我看來,所謂屬性,其實本質還是對變量的管理,屬性可以看做是對變量的封裝,通過封裝變量一來可以友善開發,省略了大量的setter/getter方法的編寫。同時也避免了直接操作變量的不安全性。在此基礎之上,屬性還有多個附加特性:nonatomic、strong、weak、copy、atomic等等,使得原本複雜的線程安全、retain/release機制等都可以通過簡單的屬性申明而避免,大大友善了程式開發。由此看來,屬性确實是objective-c相對于其他語言一個重要的優勢。
objective-c下傳統的變量并沒有太多的差別:公有、私有以及保護變量:
其含義和c++、java等語言也一樣:公有變量可以在類外部通路;私有變量僅能在類内部通路且不能被子類通路;保護變量僅能在類内部和子類通路。在objective-c中通路類變量的文法是:self->privatevar。注意必須要使用類似c++下指針的通路方式,如果使用.文法是無法通路變量的。使用諸如self->privatevar的文法通路變量就是直接操作變量,這時變量操作的安全性都是由編碼者自己負責。尤其是在操作涉及到記憶體操作的時候需要格外小心,最典型的使用場景就是在對諸如nsstring*等類型的變量進行指派操作時候的retain和release操作:
還有一點值得注意的就是,在使用屬性之後,編譯器不僅為對應的變量自動生成setter/getter方法,同時還簡化了調用兩種方法的方式:點文法。在objective-c中p.name = @"liyazhou",這樣一個語句并不是像在c++或者java下直接操作一個執行個體的類成員變量,而實際上是調用了對應的setter方法,是以p.name = @"liyazhou"調用的語句是[p setname:@"liyazhou"]。而return p.name實際上等價于return
[p getname];
以上就是objective-c下面屬性和變量最基本的差別和聯系。總的來說屬性的出現大大簡化了objective-c的程式設計,但同時也使初學者混淆了相關概念,稀裡糊塗之下随便使用,知其然不知其是以然,遇到問題不知所措。是以想要放心大膽地使用一些便利而強大的程式設計特性就必須對其背後的原理爛熟于胸才行。