I have an application that I'm writing that uses solely @properties. I have not one ivar declared at all in any of my class files. As I understand it ivars are no longer needed with the introduction of @property. Am I coding according to best practice? Will this end up biting me in the proverbial butt in the long term? I have been reading mixed reviews on what is "right" and "wrong"...
I generally don't declare ivars, either. I will often use And I always let the compiler automatically synthesize the ivar with the @synthesize foo = foo_;
though to prevent direct access when I meant through-method or vice-versa._
prefix (which prevents accidental direct access, as per the struck phrase).
And, as Caleb said, there are still ivars floating about, you just don't explicitly declare 'em unless you really want to (which, really, you don't as exposed ivars in the headers are not useful to clients of the class, if your API is designed appropriately).
I also find that the hype over "only use direct access in init/dealloc, use setter/getter everywhere else" to be largely overblown and, thus, just use the setter/getter everywhere. The reality is that if you have observers during initialization/deallocation, you are already hosed; the state of the object is, by definition, undefined during construction/destruction and, thus, an observer can't possibly reason correctly about the state.
As Caleb points out, another reason to use direct ivar access in init/dealloc is to avoid subclasses that implement custom setter/getter logic that may barf due to the undefined state of the object during init/dealloc.
While this may be true, I consider it a nasty architectural flaw to implement setters/getters with custom behavior. Doing so is fragile and makes it significantly more difficult to refactor the code over time. As well, such custom behavior will often have dependency on other state within the object and that dependency then leads to order dependencies on state changes that are not at all reflected by the seeming simple @property
declaration.
I.e. if your setters and getters are written such that foo.bar = bad;
cannot be executed at any time on foo
, then your code is busted.
_foo
. :) @Jillian that is also correct... let me expand my answer. –
Nescience foo
changes, so I'll override setFoo:
." Maybe KVO is a better way to do that. –
Jillian firstName
and lastName
might not be in a coherent, matching, state. (I.e. if I change my name from "William Bumgarner" to "Bill Bumblaster" [from when Fake SJ was funny], it takes two transactions and processing after the first would be incorrect... but what if I only change my first name?) –
Nescience valueForKey:
and setValue:forKey:
in code is generally a sign of a Design Gone Wrong. As for readonly properties, I often redeclare them as read write in a class extension at the top of my .m for internal use by my class. Especially when not using ARC, this guarantees all memory management is handled automatically through the setter/getter. –
Nescience valueForKey:
bypasses any compiler checks. Given that you have to write the code, you should just write the call. Certainly, you may be computing a key on the fly, but -- even then -- it is best to avoid or, at the least, isolate the calls behind a sensible API that does a bunch of validation internally. –
Nescience @property
for everything now, with @synthesize foo = foo_;
, no iVars anywhere. I also don't like using the dot-notation anymore, I use the setter for everything... Thanks all for your comments! –
Dwarfism foo.bar = 42
vs. [foo setBar:42]
is entirely a personal choice of style. There is no difference in the generated code. To each his own (I use .
pretty much all the time with @property
declared stuff and pretty much never -- sometimes anArray.count
or aString.length
-- otherwise). –
Nescience @synthesize foo = _foo
, instead of @synthesize foo = foo_
? –
Pelerine It's not so much that instance variables aren't needed. It's just that instance variable declarations aren't needed. Given a property and a @synthesize statement, the compiler will take care of creating the instance variable along with appropriate accessor methods.
There's nothing wrong with using properties exclusively. They simplify memory management. There's also nothing wrong with using iVars without properties, if that's what you want. If you want to use properties but don't want to advertise the accessors to the rest of the world (i.e. maintain encapsulation), consider declaring your non-public properties in a class extension (basically an anonymous category in your implementation file).
I generally don't declare ivars, either. I will often use And I always let the compiler automatically synthesize the ivar with the @synthesize foo = foo_;
though to prevent direct access when I meant through-method or vice-versa._
prefix (which prevents accidental direct access, as per the struck phrase).
And, as Caleb said, there are still ivars floating about, you just don't explicitly declare 'em unless you really want to (which, really, you don't as exposed ivars in the headers are not useful to clients of the class, if your API is designed appropriately).
I also find that the hype over "only use direct access in init/dealloc, use setter/getter everywhere else" to be largely overblown and, thus, just use the setter/getter everywhere. The reality is that if you have observers during initialization/deallocation, you are already hosed; the state of the object is, by definition, undefined during construction/destruction and, thus, an observer can't possibly reason correctly about the state.
As Caleb points out, another reason to use direct ivar access in init/dealloc is to avoid subclasses that implement custom setter/getter logic that may barf due to the undefined state of the object during init/dealloc.
While this may be true, I consider it a nasty architectural flaw to implement setters/getters with custom behavior. Doing so is fragile and makes it significantly more difficult to refactor the code over time. As well, such custom behavior will often have dependency on other state within the object and that dependency then leads to order dependencies on state changes that are not at all reflected by the seeming simple @property
declaration.
I.e. if your setters and getters are written such that foo.bar = bad;
cannot be executed at any time on foo
, then your code is busted.
_foo
. :) @Jillian that is also correct... let me expand my answer. –
Nescience foo
changes, so I'll override setFoo:
." Maybe KVO is a better way to do that. –
Jillian firstName
and lastName
might not be in a coherent, matching, state. (I.e. if I change my name from "William Bumgarner" to "Bill Bumblaster" [from when Fake SJ was funny], it takes two transactions and processing after the first would be incorrect... but what if I only change my first name?) –
Nescience valueForKey:
and setValue:forKey:
in code is generally a sign of a Design Gone Wrong. As for readonly properties, I often redeclare them as read write in a class extension at the top of my .m for internal use by my class. Especially when not using ARC, this guarantees all memory management is handled automatically through the setter/getter. –
Nescience valueForKey:
bypasses any compiler checks. Given that you have to write the code, you should just write the call. Certainly, you may be computing a key on the fly, but -- even then -- it is best to avoid or, at the least, isolate the calls behind a sensible API that does a bunch of validation internally. –
Nescience @property
for everything now, with @synthesize foo = foo_;
, no iVars anywhere. I also don't like using the dot-notation anymore, I use the setter for everything... Thanks all for your comments! –
Dwarfism foo.bar = 42
vs. [foo setBar:42]
is entirely a personal choice of style. There is no difference in the generated code. To each his own (I use .
pretty much all the time with @property
declared stuff and pretty much never -- sometimes anArray.count
or aString.length
-- otherwise). –
Nescience @synthesize foo = _foo
, instead of @synthesize foo = foo_
? –
Pelerine Using iVars certainly isn't wrong, however best practises now do push for using @property instead.
One place where you may want to use an ivar is when you want to declare a protected property. You declare the property in the .m file for a class, and declare its corresponding ivar in the .h with the @protected directive. This will then let you have a protected access in the subclass. There's no alternative for protected access to members.
© 2022 - 2024 — McMap. All rights reserved.