I don't understand something with subclassing in Objective-C : for example, we say that NSString inherits from NSObject, but does NSObject also inherits from NSString ?
I am wondering this because when I create a new class that inherits from NSObject, I have also access to NSString even if my class doesn't inherits from NSString.
For example, I can write this in my class that inherits form NSObject :
[NSString stringWithFormat:#"Hello world !"];
And what I don't understand is that I can do this even if NSString is a subclass of NSObject and not it's superclass ! !
When you call this:
[NSString stringWithFormat:#"Hello world !"];
You are sending stringWithFormat: to NSString, which defines it as a static method (or for better terms, a class method). It has nothing to do with the superclass of your class. You are mixing up basic concept of objective C and OOP in general. Subclassing means inheriting the 'traits' of the original class, and eventually extend its functionality. It does not mean that you can't call other class' methods.
The reason you can access NSString is because you gave to import Foundation.
Foundation includes NSObject and NSProxy the two public base classes provided in it.
You pretty much need all of Foundation to have a viable Objective-C library unless you are implementing your own from the ground up. Then you would have a lot of work to do.
The same is true in C or other languages. The language implementation provides some core standard libraries that give you a basis to work with.
Some parts are actually macros some are functions. Some are common essential objects
You are misunderstanding subclassing.
stringWithFormat: is a static method (class method) on NSString. You can create objects of other classes within a subclass (providing you have the necessary imports), but you cannot access methods on your class, unless it is a subclass and inherits the method, or defines the method itself.
e.g.
YourClass *testClass;
[testClass testMethod:#"Test"];
This would fail, unless testClass inherited from a class that defined testMethod:, or defined it itself.
I am a complete beginner to Objective-C programming and in fact I was confused by this :
I read that in theory, a subclass is inheriting from the methods from its superclass and not the contrary, so I just thought that if I was able to access to NSString in a class that was a subclass from NSObject, it meant that NSObject was in fact accessing to the NSString methods (which wasn't logic since NSString is a subclass of NSObject).
Finally, I just realized that if I was able to access to NSString, it was ONLY because of the "inclusion" of Fundation.h in my header with :
#import <Fundation/Fundation.h>
Related
After poking around some header files in the Foundation framework (NSString.h for example), I noticed that the declaration for NSString looks like:
#interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
/* NSString primitive (funnel) methods. A minimal subclass of NSString just needs to implement these, although we also recommend getCharacters:range:. See below for the other methods. */
- (NSUInteger)length;
- (unichar)characterAtIndex:(NSUInteger)index;
#end
The rest of the methods are declared in categories, which in turn are declared in the same header file.
After reading this answer, the implication seems to be mostly for organizing code.
Is there a benefit (other than logical grouping of methods) to declaring categories in the same header as the class declaration, especially in the case where the implementation is hidden, as in the case of NSString?
Generally, yes, categories are used for organisational purposes. But in the case of NSString they are mainly used because NSString is a class cluster. As such, the categories are used to define the additional methods (as opposed to the primitive methods) of the classes in the cluster.
There's a nice write up about class clusters from Mike Ash here.
I'm learning Objective-C and as I can see, in some tutorials they use Object(imported from objc/Object.h) and in others i see the use of NSObject(imported from Foundation/NSObject.h), but what are the main differences between they?
Regards.
You should ignore Object.
Objective-C allows multiple root classes. Object is a root class that predates NSObject. It's never something you would want to go use. It's only relevant when something somehow already interacts with Object, so you have to deal with it. This is very rare.
Object doesn't implement -retain and -release, for example.
Objective-C is just the language.
The Cocoa frameworks use the NSObject base class as the root class for the hierarchy. Other implementations use their own root classes, in your case the Object class.
NSObject contains all the infrastructure of the Cocoa framework. In other words it conforms to several protocols that Object does not and will respond to certain methods that Object will not. Specifically see NSObject Class Reference and
There are a couple of things about Objective-C that are confusing to me:
Firstly, in the objective-c guide, it is very clear that each class needs to call the init method of its subclass. It's a little bit unclear about whether or not a class that inherits directly from NSObject needs to call its init method. Is this the case? And if so, why is that?
Secondly, in the section about NSObject, there's this warning:
A class that doesn’t need to inherit any special behavior from another class should nevertheless be made a subclass of the NSObject class. Instances of the class must at least have the ability to behave like Objective-C objects at runtime. Inheriting this ability from the NSObject class is much simpler and much more reliable than reinventing it in a new class definition.
Does this mean that I need to specify that all objects inherit from NSObject explicitly? Or is this like Java/Python/C# where all classes are subtypes of NSObject? If not, is there any reason to make a root class other than NSObject?
1) Any time an object is allocated in Objective-C its memory is zeroed out, and must be initialized by a call to init. Subclasses of NSObject may have their own specialized init routines, and at the beginning of such they should call their superclass' init routine something like so:
self = [super init];
The idea being that all init routines eventually trickle up to NSObject's init.
2) You need to be explicit about the inheritance:
#instance myClass : NSObject { /*...*/ } #end
There is no reason to have a root class other than NSObject -- a lot of Objective-C relies heavily on this class, so trying to circumvent it will result in you needlessly shooting yourself in the foot.
Since it is possible to inherit from different root base classes, yes you must explicitly declare you inherit from NSObject when you make any new class (unless of course you are subclassing something else already, which itself in turn probably subclasses NSObject).
Almost never is there a need to make your own base class, nor would it be easy to do so.
Objective-C can have multiple root classes, so you need to be explicit about inheritance. IIRC NSProxy is another root class. You'll likely never want or need to create your own root class, but they do exist.
As for calling NSObject's init, it's part custom and part safety. NSObject's init may not do anything now, that's no guarantee that future behaviour won't change. Call init to be safe.
You need to call [super init] because there is code behind initializing that you dont have to write because it is written for you in NSObjects init, such as probably actual memory allocation etc.
What is the purpose/use of NSObject in Objective-C? I see classes that extend NSObject like this:
#interface Fraction : NSObject
In C++ or Java, we don't use any variables like NSObject even though we have preprocessor directives and import statements in both Objective-C and Java.
Why do classes explicitly inherit from NSObject in Objective-C? What are the consequences of not declaring inheritance from NSObject?
We use NSObject to explicitly state what a given class inherits from. I'm not sure about C++, but in Java there's something similar - the Object class. The only difference is that Java doesn't require that classes explicitly descend from Object - the language assumes anything that doesn't have a specified parent class descends from Object. Objective-C is different because it allows you to define different root classes - you are allowed to make a class that doesn't inherit from NSObject.
An example of such a different root class is NSProxy.
Have a look at the GNUstep NSObject source, it shows how the methods interact with the objective-c runtime through C functions.
+ (id) allocWithZone:(NSZone*)z
{
return NSAllocateObject(self, 0, z);
}
- (void) dealloc
{
NSDeallocateObject (self);
}
+ (BOOL) isSubclassOfClass: (Class)aClass
{
return GSObjCIsKindOf(self, aClass);
}
Since object-oriented languages have the concept of an inheritance, in any inheritance hierarchy there is a root class. In Java, the default parent class (if none is provided) is java.lang.Object, whereas in Objective-C, if you don't explicitly declare a parent class, you don't get one. Essentially, your class becomes a root class itself. This is a common mistake among Objective-C newcomers, since you normally want to inherit from NSObject in such cases.
While often problematic and puzzling, this actually allows quite a bit of flexibility, since you can define your own class hierarchies that act completely differently from NSObject. (Java doesn't allow you to do this at all.) On the other hand, unless you know what you're doing, it's easy to get yourself into trouble this way. Fortunately, the compiler will provide warnings if you call a method not defined by a class with no declared parent class, such as those you would normally expect to inherit from NSObject.
As for the "use" of NSObject, check out the documentation of the NSObject class and NSObject protocol. They define common methods used for object allocation, memory management, comparison, hashing, printing descriptions, checking class membership, querying whether objects respond to a selector, etc. Basically, NSObject is "good for" providing the core functionality of Objective-C objects free of charge.
All classes don't necessarily inherit from NSObject but it is the core for many of the classes because it provides things like alloc, retain, and release.
NSObject is the root class of all classes. In my estimation, it's 3 most basic functions are to allocate and initialize memory for you (alloc & init), as well as provide a description function.
Objective-C is all about objects sending messages to other objects -- so NSObject exists to provide that basic functionality.
If this sounds strange to you, you may wish to read more about programming paradigms, particularly object-oriented programming....In a nutshell, however, Objective C is a simple extension to the C language. C gets you the ability to program computer memory, numbers, and characters, but do anything else (like use strings, or show views, for example) you need the extension part, and NSObject is the beginning of that extension.
It may be a useful exercise to pick a class (like NSString, or any for that matter), and follow it's superclasses back to NSObject, to see what functionality each class added.
Hope that helps...
NSObject
The root class of most Objective-C class hierarchies, from which
subclasses inherit a basic interface to the runtime system and the
ability to behave as Objective-C objects.
From Apple documentation - https://developer.apple.com/documentation/objectivec/nsobject.
Basically, most of OOP programming languages explicitly or implicitly specify base class or base functionality. Otherwise you cannot build system where objects communicate with each other. Properties, memory management, message sending mechanism are partly or completely provided or supported by NSObject. Apple provide parts of the Objective-C implementation - https://opensource.apple.com/source/objc4/objc4-723/runtime/NSObject.mm.auto.html, where it's possible to see what is actually inside NSObject.
Also because Objective-C is a language from C-family, so compiler and linker needs to calculate how to layout object in memory and where put and find methods, that's only possible if you know how each of the classes/instances lays in memory and where. In case of Objective-C all base classes (NSObject, NSProxy, etc) have specification of that, so it's possible to calculate their size and add on top all inherited stuff - https://clang.llvm.org/compatibility.html#objective-c.
Consequently compiler don't let to leave a class without base class. So in the end class inheritance should lead to one of the root classes. Here is the error that appears if you don't specify it (from Xcode):
Class 'ClassWithoutBaseClass' defined without specifying a base class
For example:
#interface Fraction: NSObject {
...
When wouldn't NSObject be used and is NSObject the ultimate parent class for all other classes?
Please feel free to correct me on any wrong terminology used.
In any Cocoa app, if you examine the runtime class tree, you will find five root classes: NSObject, Object, NSProxy, NSMessageBuilder, and NSZombie.
Most ordinary objects in your app will be descended from NSObject. Object is the original root class from the early days of Objective-C, and it was superseded by NSObject when NeXT was developing the Enterprise Objects Framework.
NSMessageBuilder is used by the runtime for message forwarding. NSProxy is used by the distributed objects implementation to deal with marshaling messages to send to objects in other processes or even on other hosts. NSZombie is a class that's used for debugging memory leaks.
Cocoa has two root classes: NSObject and NSProxy.
NSObject is the root class of almost all Cocoa objects.
NSProxy is an abstract superclass defining an API for objects that act as stand-ins for other objects or for objects that don’t exist yet, and is the root class for classes like NSDistantObject.
Both classes implement the NSObject protocol.
It is also possible to write your own Objective C classes that do not have a root class, but you would probably never do that, and you would not be able to use it with Cocoa for much of anything unless you also implemented the NSObject protocol, and even then it would be of dubious use.
If I was writing a subclass of NSView, I would write:
#interface Fraction: NSView {...
because my class is inheriting from NSView. Classes in Objective-C inherit from only a single parent class. As you work your way up the chain from NSView (to its parent class, NSResponder), you would find that it eventually inherits from NSObject.
I'm not sure about the second part of your question. I think all classes in Apple's Cocoa Frameworks eventually inherit from NSObject, but don't quote me on that. There's no reason, in Objective-C, why there couldn't be other root objects (otherwise Objective-C would only be used on Apple systems). However, in Cocoa, NSObject is the root.