Before I start let me ask that in objective-c 2.0 you can have a baseclass pointer reference a subclass object?
If so is there something similar to c++ virtual member functions in objective-c.
For instance if a subclass object gets called from a baseclass pointer, will it call the subclass method (it properly overrides the base class method)? Would it be forced as well like Java or does the programmer have control over it?
Edit: would it be possible to assign any pointer type to another, what is the limit? Ex:
Can you say
Subclass *s = ...
Baseclass *b= s
Or can it only be done by allocation?
You can have a base class pointer hold onto the value of a subclass instance's address. So
Subclass s* = /* get an object instance */
Baseclass b* = s;
is possible (this doesn't have to be during init). There isn't a limit.
The "virtual method" like functionality is like Java, so every method is virtual so you don't have control over it (e.g. the subclass method is always called). Messages being sent to objects have, in effect, late binding.
See Implement a pure virtual method in Objective-C .
Related
Do Swift classes have something like an isa pointer that can be remapped?
We've seen that Swift uses a more static method dispatch than objective-C, which (unless a class dervices from Foundation/NSObject) prevents the style of swizzling based on remapping method implementations at runtime.
I'm wondering how we'll implement method interception-based dynamic features like the observer pattern, notifications, etc? Currently all this stuff is provided by the Objective-C layer, and can be easily integrated into Swift. But, if we want to provide these kinds of features in a framework (or app) of our own, is it necessary to implement them in Objective-C? I would assume there's a way to do it 'natively'.
Another kind of swizzling common to objective-C is remapping the isa-pointer to generate a sub-class on the fly. Is this kind of swizzling supported in Swift? If not what is the supported way of intercepting arbitrary method invocations?
Edit: As #jatoben points out, as of arm64 isa-remapping must be done by calling object_setClass() and not by accessing the value directly. This is still referred to as 'isa pointer swizzling'
It looks like both method exchanging and the isa pointer remapping technique only works if the Swift class has NSObject as a super-class (either directly or further up). It does not currently work, when the Swift class has no super-class or some other non-Foundation base class.
The following test shows this:
Class: Birdy
class Birdy: NSObject {
func sayHello()
{
print("tweet tweet")
}
}
Class: HodorBirdy
class HodorBirdy: Birdy {
override func sayHello()
{
super.sayHello()
print("hodor hodor")
}
}
Test:
func testExample() {
let birdy : Birdy = Birdy()
object_setClass(birdy, HodorBirdy.self)
birdy.sayHello();
}
And the output was as expected:
tweet tweet
hodor hodor
In this test both the base-class and sub-class were created in advance. Though they could also be created dynamically using the Objective-C runtime as long as the class has NSObject as an ancestor.
When a Swift class does not derive from the Objective-C foundation, then the compiler will favor static- or vtable-based dispatch, therefore its not clear how method interception will work at all in this case!
Unless the language/compiler make a specific allowance for it, we'll be foregoing dynamism in favor of performance. (Interception, which is the foundation of 'dynamic' behaviors can either be done at compile-time or run-time. In the case of static- or vtable-dispatch without a virtual machine, only compile-time applies).
I can't answer your question about swift "isa" equivalent, but I think I know part of the answer to your underlying question.
Property Observers seem to be the built-in means for the Observer Pattern. Instead of runtime discovery of "type" (RTTI, what-have-you) it is woven in explicitly.
From 'The Swift Programming Language' page 345:
Property observers observe and respond to changes in a property's
value. Property observers are called every time a property's value is
set, even if the new value is the same as the property's current
value.
You can add property observers to any stored properties you define,
apart from lazy stored properties. You can also add property observers
to any inherited property (whether stored or computed) by overriding
the property within a subclass.
You have the option to define either or both of these observers on a
property:
willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.
I am not sure how this is all going to work out, but I am intrigued.
Relying on run-time type discovery also seems to run counter to strong static type orthodoxy.
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?
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.)
I have a custom ViewController class and many instances of it, and I want them all to be able to message the same Model (another custom class, only one instance). Passing pointers to the Model along to new instances of the ViewController seems impractical, especially since the model is lazily instantiated. What is the cleanest, most idiomatic, ARC way to do this?
Usually a singleton in ObjC will have a class method that serves as an accessor for the single instance. The convention is for this to be called either defaultX or sharedX. If your model class is indeed a singleton, you should already have such a method. Since class names are globally available, all you have to do to access the instance anywhere in your program is [MyModelClass sharedModel].
I was wondering when and when not to use class methods and instance methods. I need some practical examples. I am really confused. Another question: can't we do exactly the same things with instance methods that we can with class methods?
Class methods: The method isn't tied to any specific object. In a way it acts like a free function in the class's namespace. No 'self' pointer. For instance [UIScreen mainScreen] is a class method because there's only one screen and there's no need to care about multiple 'screen instances'.
Instance method: Tied to a specific object.
This applies to most OO languages, not just obj-C.
At the implementation level, an instance method call contains a hidden pointer to a data structure (the object), a class method does not.
The practical question to ask is whether your call requires sending the call some specific data which is or could best be encapsulated as instance data inside an object, or not.
You (usually) can do the same thing with class methods as instance methods, but then you have to explicitly pass the object as a visible parameter in the call, which is uglier looking and also potentially disables some method override features of the Objective C language.
Use class methods for utility functions and Instance methods for object oriented stuff.
Eg. For Mathematical calculation (eg sin x ) use class method. But for invoking a behavior specific to an object.. use instance method ..
A class method as the name implies is bounded to the class. You can invoke them just with the name of the particular class. These can be normally exposed methods of a class.
For example
NSArray
+ (id)arrayWithArray:(NSArray *)array;.
You call it with the class name NSArray. What you expect is just a creation of a object of the type of that particular class. This doesn't need an object to invoke. Also these are very basic method required so its better to make it as a class method.
On the other hand instance method as the name implies is very much bound to the instance. Object is an entity that encapsulates state (ivars) and behaviors (methods) of a class. This can be very specific to the object.
For example
- (NSUInteger)count;
Lets take NSArray *a and NSArray *b. If a contains 5 items whereas b contains 4, instance methods called upon these instances will produce different results. And thats why we need instances to be initialized while invoking instance method. They work on the context(or state) of the object they are been called upon. Also they are not exposed as the class methods are.
Hope this helps.
If you want to use instance objet or instance variable you have to go with instance Methods.
Bcz Inside the class you cant access the Instance instance objet or instance variable.
Class methods are static methods.