I learned something new while trying to figure out why my readwrite property declared in a private Category wasn't generating a setter. It was because my Category was named:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSArray* myProperty;
#end
Changing it to:
// .m
#interface MyClass ()
#property (readwrite, copy) NSArray* myProperty;
#end
and my setter is synthesized. I now know that Class Extension is not just another name for an anonymous Category. Leaving a Category unnamed causes it to morph into a different beast: one that now gives compile-time method implementation enforcement and allows you to add ivars. I now understand the general philosophies underlying each of these: Categories are generally used to add methods to any class at runtime, and Class Extensions are generally used to enforce private API implementation and add ivars. I accept this.
But there are trifles that confuse me. First, at a hight level: Why differentiate like this? These concepts seem like similar ideas that can't decide if they are the same, or different concepts. If they are the same, I would expect the exact same things to be possible using a Category with no name as is with a named Category (which they are not). If they are different, (which they are) I would expect a greater syntactical disparity between the two. It seems odd to say, "Oh, by the way, to implement a Class Extension, just write a Category, but leave out the name. It magically changes."
Second, on the topic of compile time enforcement: If you can't add properties in a named Category, why does doing so convince the compiler that you did just that? To clarify, I'll illustrate with my example. I can declare a readonly property in the header file:
// .h
#interface MyClass : NSObject
#property (readonly, copy) NSString* myString;
#end
Now, I want to head over to the implementation file and give myself private readwrite access to the property. If I do it correctly:
// .m
#interface MyClass ()
#property (readwrite, copy) NSString* myString;
#end
I get a warning when I don't synthesize, and when I do, I can set the property and everything is peachy. But, frustratingly, if I happen to be slightly misguided about the difference between Category and Class Extension and I try:
// .m
#interface MyClass (private)
#property (readwrite, copy) NSString* myString;
#end
The compiler is completely pacified into thinking that the property is readwrite. I get no warning, and not even the nice compile error "Object cannot be set - either readonly property or no setter found" upon setting myString that I would had I not declared the readwrite property in the Category. I just get the "Does not respond to selector" exception at runtime. If adding ivars and properties is not supported by (named) Categories, is it too much to ask that the compiler play by the same rules? Am I missing some grand design philosophy?
Class extensions were added in Objective-C 2.0 to solve two specific problems:
Allow an object to have a "private" interface that is checked by the compiler.
Allow publicly-readable, privately-writable properties.
Private Interface
Before Objective-C 2.0, if a developer wanted to have a set of methods in Objective-C, they often declared a "Private" category in the class's implementation file:
#interface MyClass (Private)
- (id)awesomePrivateMethod;
#end
However, these private methods were often mixed into the class's #implementation block (not a separate #implementation block for the Private category). And why not? These aren't really extensions to the class; they just make up for the lack of public/private restrictions in Objective-C categories.
The problem is that Objective-C compilers assume that methods declared in a category will be implemented elsewhere, so they don't check to make sure the methods are implemented. Thus, a developer could declare awesomePrivateMethod but fail to implement it, and the compiler wouldn't warn them of the problem. That is the problem you noticed: in a category, you can declare a property (or a method) but fail to get a warning if you never actually implement it -- that's because the compiler expects it to be implemented "somewhere" (most likely, in another compilation unit independent of this one).
Enter class extensions. Methods declared in a class extension are assumed to be implemented in the main #implementation block; if they're not, the compiler will issue a warning.
Publicly-Readable, Privately-Writeable Properties
It is often beneficial to implement an immutable data structure -- that is, one in which outside code can't use a setter to modify the object's state. However, it can still be nice to have a writable property for internal use. Class extensions allow that: in the public interface, a developer can declare a property to be read-only, but then declare it to be writable in the class extension. To outside code, the property will be read-only, but a setter can be used internally.
So Why Can't I Declare a Writable Property in a Category?
Categories cannot add instance variables. A setter often requires some sort of backing storage. It was decided that allowing a category to declare a property that likely required a backing store was A Bad Thing™. Hence, a category cannot declare a writable property.
They Look Similar, But Are Different
The confusion lies in the idea that a class extension is just an "unnamed category". The syntax is similar and implies this idea; I imagine it was just chosen because it was familiar to Objective-C programmers and, in some ways, class extensions are like categories. They are alike in that both features allow you to add methods (and properties) to an existing class, but they serve different purposes and thus allow different behaviors.
You're confused by the syntactic similarity. A class extension is not just an unnamed category. A class extension is a way to make part of your interface private and part public — both are treated as part of the class's interface declaration. Being part of the class's interface, an extension must be defined as part of the class.
A category, on the other hand, is a way of adding methods to an existing class at runtime. This could be, for example, in a separate bundle that is only loaded on Thursdays.
For most of Objective-C's history, it was impossible to add instance variables to a class at runtime, when categories are loaded. This has been worked around very recently in the new runtime, but the language still shows the scars of its fragile base classes. One of these is that the language doesn't support categories adding instance variables. You'll have to write out the getters and setters yourself, old-school style.
Instance variables in categories are somewhat tricky, too. Since they aren't necessarily present when the instance is created and the initializer may not know anything about them, initializing them is a problem that doesn't exist with normal instance variables.
You can add a property in a category, you just can't synthesize it. If you use a category, you will not get a compile warning because it expects the setter to be implemented in the category.
Just a little clarification about the REASON for the different behavior of unnamed categories (now known as Class Extensions) and normal (named) categories.
The thing is very simple. You can have MANY categories extending the same class, loaded at runtime, without the compiler and linker ever knowing. (consider the many beautiful extensions people wrote to NSObject, that add it functionality post-hoc).
Now Objective-C has no concept of NAME SPACE. Therefore, having iVars defined in a named category could create a symbol clash in runtime. If two different categories would be able to define the same
#interface myObject (extensionA) {
NSString *myPrivateName;
}
#end
#interface myObject (extensionB) {
NSString *myPrivateName;
}
#end
then at the very least, there will be memory overrun at runtime.
In contradiction, Class extensions have NO NAME, and thus there can be only ONE. That's why you can define iVars there. They are assured to be unique.
As for the compiler errors and warnings related to categories and class extensions + ivars and property definitions, I have to agree they are not so helpful, and I spent too much time trying to understand why things compile or not, and how they work (if they work) after they compile.
Related
I have been programming for the iOS platform for the last few years but mainly using swift. In the recent months though, I have been tasked with a project using Objective C, and while I like it and found it easy to learn, there are some questions mainly about variables that I still don't quite understand.
1) What is the difference between declaring an instance variable and a property? Since the compiler automatically creates an instance variable for every property, is there any real advantage besides being able to pass in some parameters like atomic, nonatomic, strong, weak, assign, etc?
2) What is the difference between declaring variables in the #implementation or properties #interface inside the .m file?
From what I understand, declaring in the #implementation makes it a static variable and declaring it in the #interface makes it an instance variable, is that correct? Also why do classes that inherit from UIViewController (for example) already have an #interface in the .m file and classes that inherit from NSObject don't?
3) (Personal Question) Do you usually set a property to be atomic or nonatomic? I find that atomic is better because while it may be slower it is thread safe, but I see most people using nonatomic. Is the speed difference still noticeable nowadays with the amount of power we have?
4) Whenever I declare two instance variables with the same name in the #implementation in two different classes I get a "duplicate symbol" error. Why does this happen?
Just another simple question out of curiosity:
I see many questions where in the code the #interface has curly braces, but in my code I've never seen it, rather it ends with a #end like the #implementation file. Was this in earlier versions of Obj-C or is there any real difference?
Thank you so much, I know these are 4 or 5 questions, but I jumped so quickly into a project and I think I really need to learn the basics, which I skipped because I could not find answers to this questions.
1) What is the difference between declaring an instance variable and a property? Since the compiler automatically creates an instance variable for every property, is there any real advantage besides being able to pass in some parameters like atomic, nonatomic, strong, weak, assign, etc?
A property may or may not be backed by an instance variable. By default they are but you can declare a property and the explicitly provide both a getter and setter (if not read-only). Then the property will not have an implicitly declared ivar. Properties make it easy to indicate whether it is atomic or not, whether it is read-only or not, and it lets you indicate the memory management (strong, weak, copy, assign). Properties also provide support for key-value observing.
If you want a simple variable used privately without the need for any of those features, then a direct ivar without a property is over so slightly more efficient.
See Is there a difference between an "instance variable" and a "property" in Objective-c? for more details.
2) What is the difference between declaring variables in the #implementation or properties #interface inside the .m file? From what I understand, declaring in the #implementation makes it a static variable and declaring it in the #interface makes it an instance variable, is that correct? Also why do classes that inherit from UIViewController (for example) already have an #interface in the .m file and classes that inherit from NSObject don't?
The private #interface Whatever () in the .m is known as the class extension. It's basically a special unnamed category. There is no difference between declaring ivars there or in the #implementation block.
Personally I use the class extension to privately conform to protocols and to declare private properties. I use the #implementation block to declare private ivars.
Variables in the #implementation block are normal instance variables if they are put in the curly braces.
#implementation {
// ivars here
}
// variables here are globals. Same as before #implementation or after #end
// methods
#end
Without the curly braces those variables become globals.
See Difference between variables in interface Object() {} and #implementation Object #end and Difference Between Declaring a Variable Under #Implementation And #Interface Under .m file for more details.
3) (Personal Question) Do you usually set a property to be atomic or nonatomic? I find that atomic is better because while it may be slower it is thread safe, but I see most people using nonatomic. Is the speed difference still noticeable nowadays with the amount of power we have?
Atomic properties are not really thread safe. It just means the assignment is atomic and a read is atomic but it doesn't really mean thread safe in the broader sense.
See What's the difference between the atomic and nonatomic attributes? for a much more thorough discussion.
4) Whenever I declare two instance variables with the same name in the #implementation in two different classes I get a "duplicate symbol" error. Why does this happen?
See #2. You must not have your variables in the #implementation block curly braces. Put the variables where they belong and the problem goes away.
If you actually want the variable to be a file static, put it before the #implementation to make it clear that it isn't part of the class and prefix the variable declaration with static. Then if you happen to have two with the same name in different files, there won't be a duplication problem if they are static.
1) What is the difference between declaring an instance variable and a property? Since the compiler automatically creates an instance variable for every property, is there any real advantage besides being able to pass in some parameters like atomic, nonatomic, strong, weak, assign, etc?
Properties are really just methods wrapped in a syntax. They're intended to be called by other classes, assuming they're publicly provided. Instance variable is more like a field access in C. You should probably default to using properties (they support KVO, are safe on nil, etc.). You should certainly default to using properties for getting/setting, except possibly in the initializer.
Note, though, that the compiler does not always create instance variables. If you provide both getter and setter, you'll need to tell it to with #synthesize foo=_foo;.
2) What is the difference between declaring variables in the #implementation or #interface inside the .m file? From what I understand, declaring in the #implementation makes it a static variable and declaring it in the #interface makes it an instance variable, is that correct? Also why do classes that inherit from UIViewController (for example) already have an #interface in the .m file and classes that inherit from NSObject don't?
Historically, instance variables could only be defined in the #interface.
3) (Personal Question) Do you usually set a property to be atomic or nonatomic? I find that atomic is better because while it may be slower it is thread safe, but I see most people using nonatomic. Is the speed difference still noticeable nowadays with the amount of power we have?
The reason for using nonatomic is that atomic doesn't really solve thread safety as much as you'd think. For example, this is still thread unsafe, even if the property is set to atomic (since the value of foo could change between the read and write):
self.foo = self.foo + 1;
For this reason I think most favor nonatomic and handling thread safety specifically when needed.
With the current version of Objective-C, what are the official standards and best practices for declaring ivars, using #property and #synthesize? There are a lot of posts and resources on the topic but most of them are fairly antiquated from a year or two ago. I recently learned to only declare ivars in a statement block in the implementation of a class so that the encapsulation principles of OOP aren't broken but is declaring ivars even necessary in this day and age? What would be a possible use case where doing:
#interface MyClass()
#property (nonatomic) NSString* data;
#end
#implementation MyClass{
#private
NSString* _data;
}
#end
is necessary? To further that, is it ever necessary to use #synthesize? My understanding is that using #property will auto-synthesize both the accessor methods as well as the backing ivars. I've done some experimentation and I noticed that when I don't declare NSString* _data', I can still access_data' in my class implementation. Does that mean that declaring ivars come down to a matter of style, up to the discretion of the programmer? Could I condense my code and remove all ivar declarations in the statement blocks in my implementation and just use #property in my private interface? If that's not the case, what are the advantages and disadvantages of explicitly declaring ivars?
Finally, #dynamic. From what I can gather, it's used to say to the compiler, "Hey compiler, don't auto-generate the accessor method and don't worry if you don't find an implementation for it, I'll provide one at runtime". Is that all #dynamic is used for or is there more to it?
I just want to clarify all these things because it seems like there's a lot of different opinions and that there's not necessarily one right answer. Plus as Objective-C grows and progresses, those answers will change so it'll be nice to have a concise and up-to-date guide. Thanks everyone!
(Also if there's anything that I could word better or make clearer, let me know)
EDIT:
In summary, what I'm asking is this:
1) Is declaring ivars with modern Objective-C necessary?
2) Can I achieve the same effects of declaring ivars and corresponding properties by just using #property?
3) What is #dynamic used for?
4) Can I completely forgo the use of #synthesize or is there a good use case for it?
Upvote and down vote as you see fit.
There's a lot to answer here. I'll break it down:
Declaring ivars
As you've correctly noted, modern versions of the compiler will synthesize backing instance variables for declared #properties. The exception to this is on 32-bit Macs, where the modern Objective-C runtime, including non-fragile instance variables, is not available. Assuming your application is not targeting 32-bit OS X, you don't need to explicitly declare the backing ivar for an #property.
If you still want to use an ivar directly, without a corresponding #property (something I consider a bad idea most of the time), you of course must still explicitly declare the ivar.
#dynamic
#dynamic is as you've said meant to tell the compiler "don't synthesize accessors for this property, I'll do it myself at runtime". It's not used all that often. One place it is used is in NSManagedObject subclasses, where if you declare a modeled property in the header, you don't want to compiler to complain that there's no implementation of accessors for that property, nor do you want it to generate accessors itself. NSManagedObject generates accessors for modeled properties at runtime. The story is similar for custom CALayer subclasses.
#synthesize
#synthesize explicitly tells the compiler to synthesize accessor methods, and (on iOS and 64-bit Mac) a corresponding ivar for the specified property. There are three main cases where you still need to use it:
32-bit Mac apps.
If you've written your own custom setter and getter (or just getter for readonly properties). In this case, the compiler won't synthesize accessors because it sees yours. However, it also won't synthesize the backing ivar. So, you must use #synthesize someProperty = _someProperty;, to tell the compiler to synthesize an ivar. It still won't synthesize accessor methods of course. Alternatively, you can explicitly declare a backing ivar. I favor using #synthesize in this case.
If you want to use a different name for the property's backing ivar than the default (property name with an added underscore prefix). This is rare. The main case I can think of for using it is when transitioning existing, older code, that includes direct ivar access and where the ivars are not underscore-prefixed.
Best current practice seems to be to use properties for all ivars placing the property either in the .h file if they are to be exposed and in the .m file in a class extension if local to the class.
No #synthesize is needed unless the ivar needs to be different than the underscore prepended property name.
Yes, #dynamic is as you describe.
Further, it is no longer necessary to declare local instance methods or order such that the method is above the use.
First off, #synthesize is gone for these scenarios: do not have to do it any more.
Secondly, you don't need the private ivar anymore either.
So in essence, you can just do properties.
The way of controlling access is the same idiom that had become popular before MOC dropped: put the property in the public interface as readonly and then make a readwrite version in the private interface (which should be, as you show above, merely the name with open and close parens).
Note also, that many of the things that cluttered up the public interface in the past can now ONLY be in the private interface, so for instance IBOutlets, etc., since the controller is going to be the only thing diddling them.
I never see #dynamic used anywhere except in CoreDate-generated entities.
For someone who first worked with C++ where the dream was always that the header/interface merely show the user of the class what they needed and all other details would be hidden, I think MOC (Modern Objective C) is a dream come true.
BTW, highly recommend the intro session from WWDC Modern Objective C (from 2012) and the one this year was great too.
So in the guidelines it says:
For code that will run on iOS only, use of automatically synthesized instance variables is preferred.
When synthesizing the instance variable, use #synthesize var = var_; as this prevents accidentally calling var = blah; when self.var = blah; is intended.
// Header file
#interface Foo : NSObject
// A guy walks into a bar.
#property(nonatomic, copy) NSString *bar;
#end
// Implementation file
#interface Foo ()
#property(nonatomic, retain) NSArray *baz;
#end
#implementation Foo
#synthesize bar = bar_;
#synthesize baz = baz_;
#end
Question is, does this apply to public variables only or private too? It's not really clear on the documentation, but would like to have some thoughts or perspective on why "if" this is only for public or private only? I think that it just makes sense for all public/private so that you don't mess up ivars and using the property
I don't think it particularly matters whether the variables in question are public or private. The practice of synthesizing under a different name makes it explicit when you are accessing the variable directly instead of using the generated accessor method.
Perhaps there's a different question underlying what you're asking: should I typically access private ivars via the accessor or directly? I think most skilled iOS devs tend to use accessors unless there is some particular reason not to (performance, avoiding side effects like KVO, etc.). Doing so is more future-proof and allows for flexibility in the underlying implementation. In a very small way, you're coding to an interface rather than an implementation.
It also might be worth pointing out that the default behavior of Clang is going to change in the future so that property-backing ivars are synthesized named _foo by default. Clearly the powers-that-be consider consider underscoring ivars to be a best-practice.
I am pretty sure much of it comes down to personal preferences, so here are mine, for what they are worth:
I like to distinguish between public properties and "private" instance vars.
Properties are always accessed through their accessors, except for initialization (and within a manually created accessor method, for obvious reasons). Hence, the underscore in the backing ivar is useful, and not really an issue in my daily use of the properties.
Instance vars are used to hold state that is used internally in the methods, but not (directly) by other classes.
I have become very fond of declaring my instance variables in the .m file. Nice, clean and easy (no switching back and forth between .h and .m to declare ivars).
I find that this distinction helps me clear my mind and determine if a property is something outside agents should get and/or set directly (a property in .h), or if it is really just a help to get my method implementations to work (an ivar in .m).
I'd agree with Paul.s. that consistency is your friend, but to me, distinction is a friend, too.
I had some discussion related to the use of properties and instance variables at work, therefore I would like to find a wiki answer for that. Now, I know there's no real private member type in objective-c, everything is pretty much public. However, I'm a little bit concerned about the way we should design our classes and also to comply to OOP principles. I would like to hear opinions of these three design approaches:
A. According to various post and even to a new Stanford university iPhone development courses, you should always use properties everywhere you can. However IMHO, this approach brakes OOP design principles because in this case, all members become public. Why do I need to publish all my internal/local instance variables to outside? Also, there's some very little (but still) overhead if you use synthesized setters via properties, instead using local ivar directly. Here's a sample:
//==== header file =====//
#interface MyClass : NSObject
#property (nonatomic, retain) NSString *publicMemberWithProperty;
#property (nonatomic, retain) NSString *propertyForPrivateMember;
#end
B. Another approach is to declare ivars in header file (without declaring relative properties) for private members, and in the same header file, to declare pure properties (without declaring relative ivars) for public members. In such case, ivars would be used directly in the class. This approach makes sense but not uses all benefits from properties because we have manually to release old values before setting the new ones. Here's a sample:
//==== header file =====//
#interface MyClass : NSObject{
NSString *_privateMember;
}
#property (nonatomic, retain) NSString *publicMemberWithProperty;
#end
C. To declare pure properties (without declaring relative ivars) for public members in header file, and to declare pure properties (without declaring relative ivars) for private members in private interface in implementation file. This approach IMHO is more clear than the first one, but the same question remains: why do we have to have properties for internal/local members? Here's a sample:
//==== header file =====//
#interface MyClass : NSObject
#property (nonatomic, retain) NSString *publicMemberWithProperty;
#end
//==== implementation file =====//
#interface MyClass()
#property (nonatomic, retain) NSString *propertyForPrivateMember;
#end
This decision freedom annoys me a little bit and I would like to find a confirmation from respective sources about how things should be done. However, I was unable to find such strict statements in Apple docs on that, so please post a link to apple docs if any exists, or to any other theory that clears that.
By using class extensions you can have private properties.
A class extension syntax is simple:
Inside the .m-file, that has the class, create a unnamed category:
.h
#interface OverlayViewController : UIViewController <VSClickWheelViewDelegate>
- (IBAction)moreButtonClicked:(id)sender;
- (IBAction)cancelButtonClicked:(id)sender;
#end
.m
#import "OverlayViewController.h"
#interface OverlayViewController ()
#property(nonatomic) NSInteger amount;
#property(retain,nonatomic)NSArray *colors;
#end
#implementation OverlayViewController
#synthesize amount = amount_;
#synthesize colors = colors_;
//…
#end
Now you got all the aspects of properties for private members, without exposing them to public. There should be no overhead to synthesized properties to written getter/setters, as the compiler will create more or less the same at compile time.
Note that this code uses synthesized ivars. No ivar declaration in the header is needed.
There is a nice cocoawithlove article, about this approach.
You also ask why to use properties for private ivars. There are several good reasons:
properties take care for ownership and memory management.
at any point in future you can decide, to write a custom getter/setter. i.e. to reload a tableview, once a NSArray ivar was newly set. If you used properties consequently, no other changes are needed.
Key Value Coding support properties.
public readonly properties can be re-declared to private readwrite properties.
Since LLVM 3 it is also possible, to declare ivars in class extensions
#interface OverlayViewController (){
NSInteger amount;
NSArray *colors;
}
#end
or even at the implementation block
#implementation OverlayViewController{
NSInteger amount;
NSArray *colors;
}
//…
#end
see "WWDC2011: Session 322 - Objective-C Advancements in Depth" (~03:00)
There really is not a clean, safe, zero overhead, solution to this which is directly supported by the language. Many people are content with the current visibility features, while many feel they are lacking.
The runtime could (but does not) make this distinction with ivars and methods. First class support would be best, IMO. Until then, we have some abstraction idioms:
Option A
Is bad - everything's visible. I don't agree that it is a good approach, and that is not OOD (IMO). If everything is visible, then your class should either:
support all cases for how the client may use your class (usually unreasonable or undesirable)
or you provide them with a ton of rules via documentation (doc updates are likely to go unnoticed)
or the accessors should have no side effects (not OOD, and frequently translates to 'do not override accessors')
Option B
Has the deficiencies of Option A,, and like Option A, members may be accessed by key.
Option C
This is slightly safer. Like all the others, you can still use keyed access, and subclasses may override your accessors (even if unknowingly).
Option D
One approach to this is to write your class as a wrapper over over an implementation type. You can use an ObjC type or a C++ type for this. You may favor C++ where speed is important (it was mentioned in the OP).
A simple approach to this would take one of the forms:
// inner ObjC type
#class MONObjectImp;
#interface MONObject : NSObject
{
#private
MONObjectImp * imp;
}
#end
// Inner C++ type - Variant A
class MONObjectImp { ... };
#interface MONObject : NSObject
{
#private
MONObjectImp imp;
}
#end
// Inner C++ type - Variant B
class MONObjectImp;
#interface MONObject : NSObject
{
#private
MON::t_auto_pointer<MONObjectImp> imp;
}
#end
(Note: Since this was originally written, the ability to declare ivars in the #implementation block has been introduced. You should declare your C++ types there if it isn't necessary to support older toolchains or the 'fragile' 32-bit OS X ABI).
C++ Variant A is not as 'safe' as the others, because it requires the class' declaration visible to the client. In the other cases, you can declare and define the Imp class in the implementation file -- hiding it from clients.
Then you can expose the interface you choose. Of course, clients can still access your members if they really want to via the runtime. This would be easiest for them to do safely with the ObjC Imp type -- the objc runtime does not support C++ semantics for members, so clients would be asking for UB (IOW it's all POD to the runtime).
The runtime cost for the ObjC implementation is to write a new type, to create a new Imp instance for each instance, and a good amount of doubling of messaging.
The C++ type will cost practically nothing, apart from the allocation (Variant B).
Option E
Other approaches often dissociate ivars from interfaces. While this is a good thing, it's also very unusual for ObjC types. ObjC types/designs often maintain close relations to their ivars and accessors -- so you'll face resistance from some other devs.
Similarly to C++, Objective C provides public, private, and protected scopes. It also provides a package scope which is similar to package scope as defined in Java.
Public variables of classes can be references anywhere in the program.
Private variables can only be referenced within messages of the class that declares it. It could be used within messages that belong to ANY instance of the same class.
Package scope is similar to public scope within the same image, i.e. executable or library. According to Apple’s documentation, on 64-bit architectures, variables of package scope defined within a different image are to be treated as private.
Variable scope is defined by #public, #private, #protected, #package modifiers. These modifiers can be used both in a way similar to C++ or Java. All variables listed under a scope declaration belong to the same scope. Also, variables can be listed on the same line where the scope is declared.
#interface VariableScope : NSObject {
#public
int iVar0;
#protected
int iVar1;
#private
int iVar2;
#package
int iVar3;
#public int iVar01, iVar02;
#protected int iVar11, iVar12;
#private int iVar21, iVar22;
#package int iVar31, iVar32;
}
#end
For more info use the below link
http://cocoacast.com/?q=node/100
This is probably a common Objective-C question reported by Java coders, but I don't know what to call it or how to search for the answer. Let's say I have a class and another class which extends it:
AbstractModel
#interface AbstractModel {
}
ModelImpl
#interface ModelImpl : AbstractModel {
}
Separate from these, I have two more classes, again one extending the other:
ControllerA
#interface ControllerA {
AbstractModel *foo;
}
#property (nonatomic, retain) AbstractModel *foo;
ControllerB
#interface ControllerB : ControllerA {
}
I want to be able to say that foo in ControllerA can contain an AbstractModel or any of its subtypes. However, the compiler gives me a warning if I attempt to store anything other than an AbstractModel in it. (Of course I understand that classes can't really be abstract in ObjC, but have mercy on me.)
I would also like to be able to "lock down" the foo property in specific subclasses. I would like to say that foo in ControllerB can contain only a ModelImpl4 for example. Is this possible?
What is the conventional Objective-C best practice for solving this type of problem? Is using inheritance in this way -- or to achieve this goal -- just not a good idea in Objective-C?
First, I want to understand this:
However, the compiler gives me a
warning if I attempt to store anything
other than an AbstractModel in it.
This doesn't make sense. You should be able to assign sub-classes of AbstractModel to foo without trouble. What problem are you seeing?
Next, what you're describing is not overriding, it's overloading. You're trying to change the return type of the method, and you cannot do that in ObjC. There are very good solutions to this problem, but it somewhat depends on what your real goal is.
First, you can get rid of -foo in ControllerA. If ControllerA is actually abstract, then it perhaps is better not to have one. If ControllerA is abstract, I definitely recommend that you get rid of the foo ivar at that layer. You should put the ivars in the subclasses.
Alternately, you can add typed methods to the subclasses. For instance, ControllerB would have a -modelBFoo method in addition to -foo that it inherits. These methods would be identical; they would just have different return types, allowing good typing in all callers.
Do not ignore warnings. They're there to protect you (and in ObjC, they're about all you have to protect you). Limit your typecasting as much as you can. They move compiler errors (good) to run-time exceptions (bad).
Yes. The easiest way to solve the first problem is just to ignore the compiler warnings. It will work at runtime. If you don't like the warnings, you can typecast:
foo = (AbstractModel *)thisIsAModelImpl;
Then, to 'lock it down' for ControllerB, you would simply add this line to your .h file
ModelImpl *foo;
And, you would want to override (re-define) any methods dealing with foo in ControllerB.
Edit: For clarity's sake, this is what I mean by overriding.
If you have the methods (in ControllerA)
-setFoo:(AbstractModel *)newModel;
-(AbstractModel *)foo;
You would change those lines to (in ControllerB)
-setFoo:(ModelImpl*)newModel;
-(ModelImpl*)foo;