What is difference between dynamic binding Vs dynamic typing in Objective C - objective-c

I am having hard time to understand what is difference between dynamic binding Vs dynamic typing in Objective C. Can someone explain this ?

Dynamic typing in Objective-C means that the class of an object of type id is unknown at compile time, and instead is discovered at runtime when a message is sent to the object. For example, in the following code, the class of foo isn't known until we attempt to send the message componentsSeparatedByString:.
id foo = #"One Two Three";
NSArray *a = [foo componentsSeparatedByString:#" "];
If instead of using the id data type we had done the following...
NSString *foo = #"One Two Three";
...then we'd be using static typing rather than dynamic typing.
Dynamic binding means that the compiler doesn't know which method implementation will be selected; instead the method implementation is looked up at runtime when the message is sent. It basically helps us with Polymorphism. So
[foo description]
results in invoking a different method implementation if, for example, foo is an instance of NSArray rather than an instance of NSString.

with dynamic typing you can have a variable of type id that can store any type of object. with dynamic binding you can do this: id obj; [obj doWhatever]; and as long as obj is of a type that implements -(void)doWhatever it will work.

From Apple Documentation
Dynamic typing
A variable is dynamically typed when the type of the object it points to is not checked at compile time. Objective-C uses the id data type to represent a variable that is an object without specifying what sort of object it is. This is referred to as dynamic typing.
Dynamic typing contrasts with static typing, in which the system explicitly identifies the class to which an object belongs at compile time. Static type checking at compile time may ensure stricter data integrity, but in exchange for that integrity, dynamic typing gives your program much greater flexibility. And through object introspection (for example, asking a dynamically typed, anonymous object what its class is), you can still verify the type of an object at runtime and thus validate its suitability for a particular operation.
The following example illustrates dynamic typing using a heterogeneous collection of objects:
NSArray *anArray = [NSArray arrayWithObjects:#"A string", [NSDecimalNumber zero], [NSDate date], nil];
NSInteger index;
for (index = 0; index < 3; index++) {
id anObject = [anArray objectAtIndex:index];
NSLog(#"Object at index %d is %#", index, [anObject description]);
}
The object pointed to by the variable at runtime must be able to respond to whatever messages you send to it; otherwise, your program throws an exception. The actual implementation of the method invoked is determined using dynamic binding.
Dynamic binding
Dynamic binding is determining the method to invoke at runtime instead of at compile time. Dynamic binding is also referred to as late binding. In Objective-C, all methods are resolved dynamically at runtime. The exact code executed is determined by both the method name (the selector) and the receiving object.
Dynamic binding enables polymorphism. For example, consider a collection of objects including Dog, Athlete, and ComputerSimulation. Each object has its own implementation of a run method. In the following code fragment, the actual code that should be executed by the expression [anObject run] is determined at runtime. The runtime system uses the selector for the method run to identify the appropriate method in whatever the class of anObject turns out to be.
NSArray *anArray = [NSArray arrayWithObjects:aDog, anAthlete, aComputerSimulation, nil];
id anObject = [anArray objectAtIndex:(random()/pow(2, 31)*3)];
[anObject run];

If you are familiar with Javascript, dynamic typing in objective C is pretty much similar to what 'var' is in Javascript, where the actual type of this variable will be figured out at run-time and once it's assigned. It can be reused and retyped as many times as you like which makes it risky to use if you don't know the type of the object being held at the time of the execution as you as it could through 'unrecognized selector' run time exceptions. In Objective-C, all objects are of type id and therefore a variable of type id can be used for dynamic typing.
Dynamic Binding on objects is the 'polymorphic' behavior where the right method is called based on the type of object it's being called on at run time.
I hope that helps

Related

Xcode doesn't recognize properties after assigning to id

I have an NSMutableArray of two different objects inside. I am trying to recognize the first object of the array and assign it properly. Here is the example code with my idea of
// I should declare a variable here, firstly I thought about "id someObject;"
// and assigning to it in if statement.
id someObject;
if ([[someArray objectAtIndex:0] isKindOfClass:[firstOpponent class]]) {
someObject = (firstOpponent*)[someArray objectAtIndex:0];
} else {
someObject = (secondOpponent*)[someArray objectAtIndex:0];
}
[someObject method]; // this is OK
someObject.position; // property 'position' not found on object of type '__strong id'
With the idea of declaring "id someObject;" before if statement there is some problem with properties. I read that it isn't possible, thats why I'm asking for other solutions.
Your if statement achieves nothing in respect of typing.
In Objective-C a cast on a reference type, such as (firstOpponent *), does nothing at runtime; it simply allows the compiler to produce better error messages.
In your code you cast, which tells the compiler the type of the reference, and then you immediately assign to a variable of type id - which is the most general/least specific object reference type - and the compiler now knows nothing about the contents of someObject other than it contains a reference to some object.
So your code is equivalent to:
id someObject;
someObject = someArray[0];
[someObject method]; // this is OK
someObject.position; // compile time error
When calling a method on a reference typed as id, in your case someObject, the compiler does no checking and simply allows the method call. At runtime a check is done to verify the actual object references supports the method, and if not a runtime error will occur and the application will be aborted.
However the compiler will only call a property on a object whose type it knows. This is because it needs to know the type to determine what method call to translate the property access into. In general, but not always, the property access:
object.property // read a value
object.property = value // write a value
translate into the method calls:
[object property]
[object setProperty:value]
So you can access the property by doing the translation yourself and writing one of the second pair. If at runtime the reference object does not support the property then you will get an error and your application will abort.
Another option is to define a protocol, say OpponentProtocol, which declares the methods and properties all opponent classes should implement, and then have both your opponent classes implement it. You may then declare:
id<OpponentProtocol> someObject;
where the type means "any object reference as long as it implements the protocol OpponentProtocol". With such a type the compiler knows how to translate a property access into the appropriate method call, so you can access OpponentProtocol properties on someObject.
HTH
You should create a protocol that your two classes can confirm to and use id < MY_PROTOCOL > instead of just id so the compiler knows what the class is capable of responding to.

Why does the runtime allow the assignment of an NSDictionary out of an array into an NSString variable?

Consider this code:
NSMutableArray *array = [[NSMutableArray alloc]init];
for(int i = 0; i < 5 ; i++)
[array addObject:[[NSDictionary alloc]init]];
NSString *poisonedString = [array objectAtIndex:0];
In this above snippet, I have an array and I am inserting some dictionary objects into this array. While all this is fine and dandy, when I get the dictionary object from the array and put it into an string object, it is not causing any cast exceptions! The program runs smoothly and then crashes only when we do dictionary operations on the poisonedString! Why is this so? Why doesn't the Objective-C runtime see the type mismatch and raise an exception at the assignment, when the dictionary object is put into poisonedString?
Objective-C is not type-checked at runtime at all unless those checks are explicitly added. What is done at runtime is method lookup in response to a message, and in this the type of the target is not considered only whether the target has an matching method.
At compile time the Clang compiler does as much static type-checking of the Objective-C additions to C as it can to provide the programmer with warnings when types are incorrect. However the programmer can always bypass those warnings with little difficulty if they really wish to, but it is generally ill-advised to do so.
Whenever the type of something is "lost", e.g. when it is put into a collection which allows for any type of object and later extracted, then the compiler cannot provide any meaningful help. It is up to the programmer to add code to check the actual runtime type and then cast the value to the determined type. While the cast itself does nothing at runtime at compile it informs the compiler of the determined type and that allows it to do better type checking and produce better warnings.
You test the type of something with the method isKindOfClass, so the outline template is:
id someVar = ...
if ( [someVar isKindOfClass:[SpecificType class]] )
{
SpecificType *typeKnownVar = (SpecificType *)someVar;
// now use typeKnownVar and compiler will do static checking where possible
}
else
{
// deal with someVar not being of SpecificType
}
HTH
In a nutshell, NSArray supports inserting any type of object into it. If you look at the documentation you can see a generic (id) object is returned when using objectAtIndex:
- (id)objectAtIndex:(NSUInteger)index
With that in mind you can't expect the compiler to know ahead of time what type your object is when you get it from the array.
Because first of all you are not casting :) I can't see any cast, and second of all, welcome to Objective-C, this is what they call a Dynamic Language, and you can read more here
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html
Now back to your code, the arrays are not generic so you can add whatever items of whatever classes you want in the same array and when you get the item, you don't need to cast it, the compiler trusts you :D now if you try to send a message (or as you named it do some operations), it'll throw a runtime exception, so simply if you are in the situation where you don't know if it's an NSString or an NSDictionary, just use the below code to check the type of the object.
if ([array[0] isKindOfClass:[NSDictionary class]]) {
// Do whatever you want
}
else if ([array[0] isKindOfClass:[NSString class]]) {
// Also do whatever you want
}
in NSArray class reference the documentation present that the return of ObjectAtIndex is an id
objectAtIndex:
Returns the object located at the specified index.
- (id)objectAtIndex:(NSUInteger)index
It is not possible to the compiler to know the type of object when your pointer is an id. It's normal that dump at executing time and not at compiling time.

How is type safety possible for an object pointer of id?

I have the following class (picked out of a Apple example):
#interface LeTemperatureAlarmService : NSObject <CBPeripheralDelegate>
#property (readonly) CBPeripheral *servicePeripheral;
#end
and in a different class's method I use the following code:
NSMutableArray *connectedServices = [[NSMutableArray alloc] init];
... // Adding some myService objects to connectedServices
for (id service in connectedServices) {
if ([service servicePeripheral] == parameter) {
...
}
}
Now the thing which drives me crazy is the part where I can send servicePeripheral to service.
As far as I understand how id works, it's basically a pointer which can be literally point to any object. My NSMutableArray is an untyped array which can hold any type of object in it, even mixed, so I don't have to be careful what I put in.
So how can it be that I can use [service servicePeripheral] even though I never specified the type of service? And how does Xcode know that and even suggest that method in code completion?
Objective-C works different in the respect of method invocation than say C++. The compiler doesn't have to know, because it's not done at compile time, methods are invoked at runtime. Specifically, methods are send to objects, instead of called on them. You send the servicePeripheral method to the object and the runtime takes care of calling the right function. This also makes it possible for you to send methods to nil without crashing (it will return false/0/NULL)
Types in Objective-C are mostly used for compile time safety, which you lose with your approach. The compiler can't warn you that the types don't match, for instance, your array can very well contain NSString instances or anything, and the compiler can't help you there since you tell it that you expect id (aka anything, really) and servicePeripheral is a perfectly valid and known method. You can add type safety by checking the class of the object at runtime using isKindOfClass:, for example like this:
for (id service in connectedServices) {
if ([service isKindOfClass:[LeTemperatureAlarmService class]] && [service servicePeripheral] == parameter) {
...
}
}
So how can it be that I can use [service servicePeripheral] even though I never specified the type of service?
It is exactly because you declared service as an id. This tells the compiler to turn off all static type-checking and permit you to send any message to service. That is what id is: it is the universal recipient (any message can be sent to it, any object value can be assigned to it) and the universal donor (it can be assigned to any object variable).
And you are perfectly right to be wary of this, since it can cause you to crash later. It is not (as your question title has it) "type safety". It is type unsafety! The compiler will happily let you say (for example) [service count] (because service is typed as an id), but you will crash later when the app runs, because this object does not respond to the count message.
So don't do that! Use explicit types so the compiler can help you in advance.

Objective-C Containers that take objects

I'm doing my first steps in objective-c (after a long, long time away from it) by translating some Java code I wrote for an Android game. It seems like there is no container that can take an object, without casting it to id first? Or is there?
Specifically this is the code I'm trying to work with:
NSMutableArray *touchedBodies = [[NSMutableArray alloc] init];
// some additional code
if(![touchedBodies containsObject:(id)body]) {
[touchedBodies addObject:(id)body];
}
The containsObject line passes fine, but on the touchedBodies addObject:(id)b I'm getting a "bad access" error. The body I'm trying to add is a legitimate Box2D b2Body.
When I tried to add the body directly, without casting it:
[touchedBodies addObject:body];
the compiler complains "Cannot initialize a parameter of type id with an lvalue of type b2Body* '
What am I missing?
First of all you never need to cast to an id type just because you can consider id as the Object class in Java: it's an implicit upcast that doesn't need to be explicit.
In second instance the problem occurs because 2dBody is a C++ class, not an Objective-C class. While you can mix Objective-C++ and C++ code (the former is a superset of the latter), you can't mix objects from these two languages without some workarounds.
You have mainly three solutions:
if 2dBody is a pointer, wrap it inside an NSValue: [touchedBodies addObject:[NSValue valueWithPointer:body]], this introduces some overhead with object allocations and you will need to cast it when you use it, 2dBody *b = (2dBody*)[value pointerValue]
if 2dBody is not a pointer then you could use an NSData: [NSData dataWithBytes:.. length:..], this introduces overhead, problems with memory management (unless you use noCopy variants), it introduces problems if the layout of the class is not standard, and you will need to cast it in any case
forget cocoa collections and use STL collections, they're more performant and they will manage everything seamlessly: vector<2dBody> touchedBodies; touchedBodies.push_back(body);.
I strongly suggest using STL collections, I personally use this approach

Are pointers to arguments in Objective C methods are const by default?

There are methods in Cocoa classes that accept an address of a pointer. Most commonly the argument is address of future NSError * object in CoreData validation methods (among others). This way it is possible to put custom or owned object into the place of the address that given argument points to.
My question is: why can't we do that with simple pointer arguments? E.g. let's say I have a method:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array;
I can easily pass the mutable array as second argument, call addObject: on it and after the method call the array will be modified. Why is this not done with NSError * objects? Are pointers passed to methods are defined as const by default? Is this to avoid accessing NULL?
Why is this not done with NSError * objects?
Because there's no such thing as an NSMutableError. Your example works because you can modify the contents of the array without modifying the pointer to the array itself. However, since NSError instances are immutable, you cannot modify an NSError. As such, you must necessarily create a new error object. And if you want to return that error object along with some other piece of data, at least one of those must be done via an out-parameter (such as an NSError **).
Are pointers passed to methods are defined as const by default?
Nope. Inside that method you're welcome to do this:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array {
someObject = somethingElse;
[array addObject:someObject];
}
What's important to remember here is that you're only changing a pointer in a slot in memory. The memory slot corresponding to someObject is just a space on the stack, and you're changing the contents of that space to have a value that points to a different allocated object than the one you were given.
Is this to avoid accessing NULL?
Any NULL protection you need must be done yourself.
It's because the NSError class does not define any way to modify instances after creation. The pointer itself is mutable, but an NSError is not.
They are all plain C pointers. They are not const unless you make them const. Const pointers are not a good thing to use in most situations in objective-C, or even often plain C. Const pointers are a subtle concept, and the complexities of the meaning and syntax don't mesh well with the Objective-C style of programming. Forgetting they exist is likely a good first approximation.
Example: NSArray and NSMutableArray - we would not need an NSArray class if const worked 'correctly' - but it can't due to the design of C.
** - For NSError, etc., the idea is to create an NSError, not alter the one you have passed in. In other words, you need a pointer to a pointer to be able to create an instance (i.e. change the actual object).