I have recently started a personal curriculum to learn how to code in Objective-C. At this point I have barely begun to scratch the surface. This is my first of set of notes, which focus on the structure of Objective-C from a purely conceptual standpoint. I hope this material can also be helpful to others, and let me know if you have anything to add. You can download a pdf copy of these notes here.
These notes will probably only make sense to you if you have some knowledge of object-oriented programming. My source material to date has been limited to a few sections of the documentation from the Apple Developer Website, and an excellent 4-hour kitchen table session by Nolen & Pitaru.
Why is Objective-C a Dynamic Language
Objective-C is a truly dynamic object oriented programming language. It was designed to make to shift as much of the decision making as possible to runtime, from compile time and link time. This is in contrast to most other languages, both procedural and object-oriented ones, which mandate that variable typing and relationships be defined in the source code at compile time.
Dynamic languages are ideal for systems where components are loosely coupled, such as in user interface design and development. They allow applications to be structured like networks of objects that are able to work together to respond to external events. The objects act as “agents” that work in a coordinated fashion to carry out the program’s intent. Each object has a particular role to play, and within that role it can act fairly independently of the other parts of the program.
Ok, up until this point it sounds pretty much like standard object-oriented programming mumbo jumbo. This is where it starts to get interesting. In Objective-C, the messaging architecture separates the message (the requested behavior) from the receiver (the owner of a method that can respond to the request). The messaging metaphor is used to capture the idea that behaviors (or methods, in old school oop parlance) can be abstracted away from their particular implementations (or classes).
Ultimately this means that at compile-time objects only need to know the abstract behaviors, or actions, they can request from other objects. The concrete behaviors that is actually requested is only determined at run-time, when the recipient of the message is identified.
Let’s dig a little deeper into the three specific types of dynamism provided by Objective-C, and the new possibilities they create. Here is a short list followed by brief descriptions along with short overviews of the possibilities create by each one.
- Dynamic typing: identifying the class of an object at runtime
- Dynamic binding: determining what method to invoke at runtime
- Dynamic loading, adding new components to a program at runtime
i. Dynamic Typing
Dynamic Typing permits the type of an object be determined at runtime rather than forcing it to be defined statically in your code. This creates the following possibilities:
- An object can be passed via a message without defining what kind of object it is at compile-time. The type of object being passed is only determined during runtime.
- An object that is receiving, and responding to, a message can also be left undefined until runtime. Therefore, the action will be taken is only determined at run-time when the receiving object is identified.
ii. Dynamic Binding
Dynamic Binding enables the program to determine which method to invoke at runtime. Dynamic typing and dynamic binding are closely related. They work together to open up the following possibilities:
- Message can have very different results depending on the class of the receiver, which is determined when the program is running based on runtime factors.
- Messages can be sent to objects that were not invented when your code was originally written. New classes just need to agree on the messages to enable communications from your code.
Dynamic binding available in Objective-C differs from late binding, which is a more limited type of dynamic binding supported by many object oriented languages such as C++ and Java. Late binding enables an object to be typed using a generic, or high-level, type. At run-time the actual objects handled by the application are sub-types that inherits from the generic type defined in the source code. As you will note, this type of binding still requires that a specific type be identified at compile-time.
iii. Dynamic Loading
Dynamic Loading allows different parts of an executable program to be separated into their own files. The program is then launched in bits and pieces, new parts are dynamically loaded and linked as they’re needed. Dynamic loading raises several interesting possibilities:
- It enables software to be developed in a more modular fashion. An entire program does not have to be developed at once; it can be delivered and updated one part at a time.
- Programs can run more efficiently by enabling users to load just the tools that they need, enabling users to grouping of tools under a single interface, and enabling them to select between, and load, different tools to do the same job.
- It makes your application more extensible, making it easier to add to and customize your creation. All your program needs to do is provide a framework that others can fill in, and, at runtime, find the pieces that they’ve implemented and load them dynamically.