For the More Curious: Property Synthesis

When explaining properties in this chapter, we noted that a property automatically generates the implementation for the accessor methods and it declares and creates an instance variable. While this is true, we omitted the fact that this behavior is only the default and you have other options.

Declaring a property in a class interface only declares the accessor methods in a class interface. In order for a property to automatically generate an instance variable and the implementations for its methods, it must be synthesized, either implicitly or explicitly. Properties are implicitly synthesized by default. A property is explicitly synthesized by using the @synthesize directive in an implementation file:

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​P​e​r​s​o​n​

/​/​ ​G​e​n​e​r​a​t​e​s​ ​t​h​e​ ​c​o​d​e​ ​f​o​r​ ​-​s​e​t​A​g​e​:​ ​a​n​d​ ​-​a​g​e​,​
/​/​ ​a​n​d​ ​c​r​e​a​t​e​s​ ​t​h​e​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​ ​_​a​g​e​
@​s​y​n​t​h​e​s​i​z​e​ ​a​g​e​ ​=​ ​_​a​g​e​;​


/​/​ ​O​t​h​e​r​ ​m​e​t​h​o​d​s​ ​g​o​ ​h​e​r​e​

@​e​n​d​

This is how properties are automatically synthesized. The first attribute (age) says create methods named age and setAge:, and the second attribute (_age) says the instance variable that backs these methods should be _age.

You can optionally leave off the variable name, which creates a backing variable with the same name as the accessors.

@​s​y​n​t​h​e​s​i​z​e​ ​a​g​e​;​
/​/​ ​I​s​ ​t​h​e​ ​s​a​m​e​ ​a​s​:​
@​s​y​n​t​h​e​s​i​z​e​ ​a​g​e​ ​=​ ​a​g​e​;​

There are cases where you do not want an instance variable to back a property and therefore do not want a property to automatically generate the accessor method implementations. Consider a Person class with three properties, spouse, lastName, and lastNameOfSpouse:

@​i​n​t​e​r​f​a​c​e​ ​P​e​r​s​o​n​ ​:​ ​N​S​O​b​j​e​c​t​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​s​t​r​o​n​g​)​ ​P​e​r​s​o​n​ ​*​s​p​o​u​s​e​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​c​o​p​y​)​ ​N​S​S​t​r​i​n​g​ ​*​l​a​s​t​N​a​m​e​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​c​o​p​y​)​ ​N​S​S​t​r​i​n​g​ ​*​l​a​s​t​N​a​m​e​O​f​S​p​o​u​s​e​;​
@​e​n​d​

In this somewhat contrived example, it makes sense for both the spouse and lastName properties to be backed by an instance variable. After all, this is information that each Person needs to hang onto. However, it does not make sense to hold onto the last name of the spouse as an instance variable. A Person can just ask their spouse for their lastName, so storing this information in both Person instances is redundant and therefore prone to error. Instead, the Person class would implement the getter and setter for the lastNameOfSpouse property like so:

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​P​e​r​s​o​n​
-​ ​(​v​o​i​d​)​s​e​t​L​a​s​t​N​a​m​e​O​f​S​p​o​u​s​e​:​(​N​S​S​t​r​i​n​g​ ​*​)​l​a​s​t​N​a​m​e​O​f​S​p​o​u​s​e​
{​
 ​ ​ ​ ​s​e​l​f​.​s​p​o​u​s​e​.​l​a​s​t​N​a​m​e​ ​=​ ​l​a​s​t​N​a​m​e​O​f​S​p​o​u​s​e​;​
}​

-​ ​(​N​S​S​t​r​i​n​g​ ​*​)​l​a​s​t​N​a​m​e​O​f​S​p​o​u​s​e​
{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​s​e​l​f​.​s​p​o​u​s​e​.​l​a​s​t​N​a​m​e​;​
}​
@​e​n​d​

In this case, because you have implemented both accessors, the compiler will not automatically synthesize an instance variable for lastNameOfSpouse. Which is exactly what you would hope for.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset