Are classes objects in Objective-C? - objective-c

okay, so I understand that an object is an instance of a class that must be allocated and initialized, but are classes themselves objects?
I know when you create a new class it is an instance of something else, like NSObject. So, if this makes it a class, then objects can hold not only variables and methods, but other objects as well, right?
Sorry, this is probably really basic, but I am reading two books about cocoa and xcode and this point is a little unclear (probably because of my lack of experience in other languages).

Here is a pretty good explanation of the matter by Greg Parker
Quoting:
[...] Each Objective-C class is also an
object. It has an isa pointer and
other data, and can respond to
selectors. When you call a "class
method" like [NSObject alloc], you are
actually sending a message to that
class object.
Since a class is an object, it must be
an instance of some other class: a
metaclass. The metaclass is the
description of the class object, just
like the class is the description of
ordinary instances. In particular, the
metaclass's method list is the class
methods: the selectors that the class
object responds to. When you send a
message to a class - an instance of a
metaclass - objc_msgSend() looks
through the method list of the
metaclass (and its superclasses, if
any) to decide what method to call.
Class methods are described by the
metaclass on behalf of the class
object, just like instance methods are
described by the class on behalf of
the instance objects.
What about the metaclass? Is it
metaclasses all the way down? No. A
metaclass is an instance of the root
class's metaclass; the root metaclass
is itself an instance of the root
metaclass. The isa chain ends in a
cycle here: instance to class to
metaclass to root metaclass to itself.
The behavior of metaclass isa pointers
rarely matters, since in the real
world nobody sends messages to
metaclass objects. [...]
Further interesting reads:
Understanding the Objective-C Runtime by Colin Wheeler
(search for paragraph titled "So Classes define objects…")
What is a meta-class in Objective-C? by Matt Gallagher

Related

What is a class object in Objective-C 2.0?

In the official documentation for Objective C 2.0 titled The Objective-C 2.0 Programming Language from Apple, released in 2009, there is a paragraph about Class Objects on page 28.
I don't understand what Class Objects are, and how to define them aside from the rest of the language and what properties they have. In the same document it's explained that everything in Objective-C 2.0 is an object, this object is basically a pointer to a struct that contains an isa field and the pointer itself is of type id.
From this I'm deducing that:
inheritance in Obj-C 2.0 basically consists in chaining those struct through the id and isa field
objects that are superclass construct the isa field in a way that it points to a nil object.
id is a valid datatype for pretty much everything in Objective C 2.0
when defining a class, everything that defines the class itself ( methods and variables ) is packed starting from after/below the isa pointer
Assuming that I got how Objective C 2.0 works, what is a class object and how is it different from the way instances are created? What kind of properties does a class object offer that an instance doesn't have ? Can you make a parallel with C or C++?
OK, so you define a class. We'll call him Charlie:
#interface Charlie : NSObject
#end
There's our little class! Since — like every other class in Obective-C — Charlie is an object, you can send it messages like [Charlie alloc] to have Charlie allocate an instance for you. This is what we mean by a class object: It's the object that represents the class you defined.
What is an object in Objective-C? Classes are defined based on this struct:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
And a class is represented by a struct like this:
struct objc_class {
struct objc_class *isa;
struct objc_class *super_class;
// A bunch of other members …
}
As you can see, the both start with an isa referring to a class. So a class is just an extension of normal objects.
When Charlie creates an instance, that instance's isa will point to Charlie. But what does Charlie's isa point to? Well, it points to a metaclass. A metaclass is a strange thing — it's a special kind of class that exists just to act as a class's class. You never interact with it directly; it just does its classly duties† when you interact with its sole instance, Charlie.
So that's what we mean when we talk about a class object — it's just the object that represents the class you defined in code.
† You might be wondering what a class's duties are. Well, the obvious biggie is that it's how you create your objects. But besides that, instances in Objective-C do not hold their own methods. Instead, method resolution is done based on an object's isa, so the class's most important function, besides creating instances for you, is determining what methods your object has.
what is a class object and how it's different from the way instances
are created ? What kind of properties a class object offers that an
instance doesn't have ? Can you make a parallel with C or C++ ?
Let's try to compare with C and C++. First there is no comparison to C, because C is not object oriented, so the concept of object or class does not exist. In C++ you have classes (or objects) which you declare in your .h file, there you write the definition of the class (the name, the instance variables, and methods or functions), and then in your .cpp file you implement the methods declared in the definition.
Also in C++ you can have static variables and methods, which, as you probably know, don't belong to a specific instance of the class, we could say that they affect all instances.
In objective C, a class property or a class method is analogous to the static variables and static funcions in C++.
A class object is the way objective C encapsulates the definition of a class and makes it available at runtime. You don't necessarily instantiate class objects explicitly.
Consider this class
#interface MyObject : NSObject
{
int i;
}
- (void)myFunction;
+ (void)classFunction;
#end
You can instantiate such an object using:
MyObject *obj = [[MyObject alloc] init];
Here you're using the alloc method of the MyObject class object. Something important to understand is that you don't instantiate class Objects, the compiler creates just one object, a class object, to represent the class.
Object is a structure, that has isa field pointing to its Class. This isa allows the structure to receive Objective-C messages, which makes it an Object. Class pointed by isa is used to lookup implementations for these messages.
(Interestingly, also blocks are objects and GCD structures are too. They both can receive messages, like -copy for blocks or -description for dispatch_queue.)
Class is a structure used to look-up methods of its instances. It has a list of method implementations for their instances (-methods). Classes have an isa field, so they qualify as Objects, thus can also receive messages. isa of Class points to a Metaclass, so a Class is instance of a Metaclass. Its single instance – a singleton.
Metaclass is where I'm getting lost, but it's definitely an Object, because it has isa. Metaclass has a list of method implementations (+methods) of its single instance – the Class.
When you write this code:
#interface MYObject : NSObject
+ (void)classMethod; // Stored in Metaclass
- (void)instanceMethod; // Stored in Class
#end
You are creating a pair: Class and Metaclass.
Oh, and what is a class of Metaclass? A Root Metaclass!
And what is a class of the Root Metaclass? The Root Metaclass itself!
But then where isa of Metaclasses points to? To our old friend NSObject. Too meta, right?

Understanding abstract superclass NSNumber

I am reading some book about objective C ,and they say there that NSNumber is an abstract superclass of many subclasses that we can use .
So, "when we call a method in NSNumber, the appropriate subclass is used" .
This is not going with some other rule that i know :
if superclass A, has subclass B , and you calling a method in the super class A , that is in the subclass B, you can't do that- because inheritance is working all the way up and not down.
So, how is that the superclass (abstract) class- NSNumber, is using its subclass methods ??
What is the hierarchy here ?
Thanks .
It's done through class cluster pattern.
From documentation:
The abstract superclass in a class cluster must declare methods for
creating instances of its private subclasses. It’s the superclass’s
responsibility to dispense an object of the proper subclass based on
the creation method that you invoke—you don’t, and can’t, choose the
class of the instance.
Whenever you create number with some factory method, like +numberWithInt: the factory returns instance of concrete subclass. Afterwards, when you call something like -stringValue: this selector is sent to instance of concrete NSNumber subclass - int in this case.
So, NSNumber factory methods actually does not return NSNumber objects - they return concrete subclasses. Same is true for other Cocoa class clusters - NSArray, NSDictionary, NSSet.
In effect there are classes NSDoubleNumber, NSLongLongNumber, NSIntegerNumber, etc, (made-up names) and you get the appropriate one. But as with all subclassing, if you then call a method of the object via it's superclass type it will respond, invoking the class-specific method appropriate to that instance.
Objective-C muddles things slightly, since if you ask what the class is it won't return "NSDoubleNumber" or whatever but instead returns an essentially meaningless name for the whole cluster, or for a particular subdivision of it.
The point is, you can treat the instances as objects of the single fictitious class "NSNumber" and never need to worry about which subclass you actually have.
(BTW, similar things are true of NSArray, NSDictionary, and a number of other classes.)

-forwardInvocation for class methods

I'm struggling to forward a class method through a facade class.
To clarify, I'm overriding all the following methods:
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
-(void)forwardInvocation:(NSInvocation *)anInvocation
+(BOOL)instancesRespondToSelector:(SEL)aSelector
+(NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector
+(IMP)instanceMethodForSelector:(SEL)aSelector
+(BOOL)resolveClassMethod:(SEL)sel
+(BOOL)resolveInstanceMethod:(SEL)sel
.. and yet, for the class method, the only one to be called is +resolveClassMethod. From there, I immediately get an unrecognized selector exception regardless of whether I return YES or NO.
What's going on?
Does class message forwarding work differently to instance message forwarding?
Similarly, why isn't there a +forwardInvocation class method?
Any help would be greatly appreciated.
So you already know that to make an object do forwardInvocation for instance methods, you have to implement the instance methods -forwardInvocation: and -methodSignatureForSelector: (the others are unnecessary). Well, class methods are just methods on the class object. Classes are objects and work like any other objects, and support all the instance methods of the root class (NSObject in this case).
The Objective-C runtime doesn't care that an object is a class object or non-class object. The message forwarding mechanism is the same. So when you send a message to an object, whatever it is, and it can't find it, it just looks for the forwardInvocation: and methodSignatureForSelector: methods on the object. So you need to have these methods on your class object.
i.e. implement the class methods +forwardInvocation: and +methodSignatureForSelector:

Can an ObjC class object conform to a protocol?

Is there a way to indicate to the compiler that a class object conforms to a protocol?
As I understand, by creating +(void)foo class methods, an instance of that class object will have those methods as instance methods. So, as long as I create +(void)foo methods for all required protocol methods, I can have a class object act as a delegate.
My problem of course is that in the class's header file, I only know how to indicate that instances of the class conform to the protocol (as is typically the case). So, the best I've figured out is to cast the class object like so:
something.delegate = (id<SomethingDelegate>)[self class]
Any ideas?
Related, but different:
ObjC: is there such a thing as a "class protocol"?
What you're doing now is correct as it will silence warnings which is your goal. You will be sending the class object messages defined in the protocol for instances which is a bit confusing, but the runtime doesn't care.
Think about it this way: you want to set a delegate to an object that responds to the messages defined in the protocol. Your class does this, and your class is also an object. Therefore, you should treat your class like an object that conforms to that protocol. Therefore, what you've written is completely correct (based on what you're trying to do).
One thing to note, though, is this class will not properly respond to conformsToProtocol:. This is generally okay for a delegate setup anyway (delegates don't usually check if the class conforms — they just check if it can respond to a selector).
As a side note, one thing you can do syntactically is:
Class<SomethingDelegate> variable = (Class<SomethingDelegate>)[self class];
The difference here is that the compiler will use the class methods from the protocol instead of instance messages. This is not what you want in your case, though.
There is no Objective-C syntax to indicate that a metaclass conforms to a protocol.
I think you can do it at runtime, by using class_addProtocol on the metaclass. But I haven't tried it.
I guess you could also write a +conformsToProtocol: method on your class, and lie about your conformance. This could have unexpected side-effects, since there's already a +conformsToProtocol: on NSObject (in addition to -conformsToProtocol:).
Neither of these will eliminate the need for a cast to shut the compiler up. Just use a singleton.

Do I need to Subclass from NSObject?

I'm starting Objective-C Development and I'm trying to wrap my head around how some things work.
I'm creating a Twitter Client and have a class "Tweet". This is just a DTO - a class that has some variables.
Should this just be a class or should it inherit from NSObject?
Why? Or why not?
Every normal class should subclass from NSObject. Basic memory management like -retain and -release, and runtime introspection like -isKindOfClass:, -respondsToSelector: cannot work without it.
You should, unless you have a very explicit, strong reason not to. In Objective-C, any object can be assigned to an id. But id doesn't guarantee any methods at all, even the standard operations such as allocation, initialization, deallocation and reference counting.
These are implemented by a root class, which is almost always an NSObject.
Also, most of the Cocoa API expects to deal with an NSObject, because it needs to at least retain and release the object.
So you should inherit from NSObject.