Objective-C

From Seo Wiki - Search Engine Optimization and Programming Languages
Jump to navigationJump to search
Objective-C
Paradigm reflective, object oriented
Appeared in 1986
Designed by Tom Love and Brad Cox
Developer Apple Inc.
Stable release Objective-C 2.0
Typing discipline static, dynamic, weak
Major implementations Apple Cocoa, clang LLVM, GCC
Influenced by Smalltalk, C
Influenced TOM, Java, Objective-J

Objective-C is a reflective, object-oriented programming language, which adds Smalltalk-style messaging to the C programming language.

Today it is used primarily on Apple's Mac OS X and iPhone OS: two environments based on, although not compliant with, the OpenStep standard.[1] Objective-C is the primary language used for Apple's Cocoa API, and it was originally used as the main language on NeXT's NeXTSTEP OS. Generic Objective-C programs which do not make use of these libraries can also be compiled for any system supported by gcc, which includes an Objective-C compiler.

History

Objective-C was created primarily by Brad Cox and Tom Love in the early 1980s at their company Stepstone. Both had been introduced to Smalltalk while at ITT Corporation’s Programming Technology Center in 1981. Cox had become interested in the problems of true reusability in software design and programming. He realized that a language like Smalltalk would be invaluable in building development environments for system developers at ITT. Cox began by modifying the C compiler to add some of the capabilities of Smalltalk. He soon had a working implementation of an object-oriented extension to the C language, which he called "OOPC" for Object-Oriented Programming in C. Meanwhile, Love was hired by Schlumberger Research in 1982 and had the opportunity to acquire the first commercial copy of Smalltalk-80, which further influenced development of their brainchild.

In order to demonstrate that real progress could be made, Cox showed that making interchangeable software components really needed only a few practical changes to existing tools. Specifically, they needed to support objects in a flexible manner, come supplied with a usable set of libraries, and allow for the code (and any resources needed by the code) to be bundled into a single cross-platform format.

Love and Cox eventually formed a new venture, Productivity Products International (PPI), to commercialize their product, which coupled an Objective-C compiler with class libraries. In 1986, Cox published the main description of Objective-C in its original form in the book Object-Oriented Programming, An Evolutionary Approach. Although he was careful to point out that there is more to the problem of reusability than just the language, Objective-C often found itself compared feature for feature with other languages.

Popularization through NeXT

After Steve Jobs left Apple, he started the company NeXT. In 1988, NeXT licensed Objective-C from StepStone (the owner of the Objective-C trademark) and released its own Objective-C compiler and libraries on which the NeXTstep user interface and interface builder were based. Although the NeXT workstations failed to make a great impact in the marketplace, the tools were widely lauded in the industry. This led NeXT to drop hardware production and focus on software tools, selling NeXTstep (and OpenStep) as a platform for custom programming.

The GNU project started work on its free clone of NeXTStep, named GNUstep, based on the OpenStep standard. Dennis Glatting wrote the first gnu-objc runtime in 1992. The GNU Objective-C runtime, which has been in use since 1993, is the one developed by Kresten Krab Thorup when he was a university student in Denmark. Kresten also worked at NeXT from 1993 to 1996.

After acquiring NeXT in 1996, Apple Inc. used OpenStep in its new operating system, Mac OS X. This included Objective-C and NeXT's Objective-C based developer tool, Project Builder (later replaced by Xcode), as well as its interface design tool, Interface Builder. Most of Apple's present-day Cocoa API is based on OpenStep interface objects, and is the most significant Objective-C environment being used for active development.

Syntax

Objective-C is a thin layer on top of C, and moreover is a strict superset of C. It is possible to compile any C program with an Objective-C compiler, and to freely include C code within an Objective-C class.

Objective-C derives its object syntax from Smalltalk. All of the syntax for non-object-oriented operations (including primitive variables, preprocessing, expressions, function declarations, and function calls) is identical to that of C, while the syntax for object-oriented features is an implementation of Smalltalk-style messaging.

Messages

The Objective-C model of object-oriented programming is based on message passing to object instances. In Objective-C one does not call a method; one sends a message. This is unlike the Simula-style programming model used by C++. The difference between these two concepts is in how the code referenced by the method or message name is executed. In a Simula-style language, the method name is in most cases bound to a section of code in the target class by the compiler. In Smalltalk and Objective-C, the target of a message is resolved at runtime, with the receiving object itself interpreting the message. A method is identified by a selector or SEL — a NULL-terminated string representing of its name — and resolved to a C method pointer implementing it; an IMP.[2] A consequence of this is that the message passing system has no type checking. The object to which the message is directed — the receiver — is not guaranteed to respond to a message, and if it does not it simply raises an exception.[3]

Sending the message method to the object pointed to by the pointer obj would require the following code in C++:

obj->method(parameter);

In Objective-C, this is written as follows:

[obj method: parameter];

Both styles of programming have their strengths and weaknesses. Object-oriented programming in the Simula style allows multiple inheritance and faster execution by using compile-time binding whenever possible, but it does not support dynamic binding by default. It also forces all methods to have a corresponding implementation unless they are virtual (an implementation is still required for the method to be called). Smalltalk-style programming allows messages to go unimplemented, with the method resolved to its implementation at runtime. For example, a message may be sent to a collection of objects, to which only some will be expected to respond, without fear of producing runtime errors. (The Cocoa platform takes advantage of this, as all objects in a Cocoa application are sent the awakeFromNib: message as the application launches. Objects may respond by executing any initialisation required at launch.) Message passing also does not require that an object be defined at compile time. (See the dynamic typing section below for more advantages of dynamic (late) binding.)

It should be noted, however, that due to the overhead of interpreting the messages, an initial Objective-C message takes three times as long as a C++ virtual method call. Subsequent calls are IMP cached and 50% faster than the C++ virtual method call.[4]

Interfaces and implementations

Objective-C requires that the interface and implementation of a class be in separately declared code blocks. By convention, the interface is put in a header file and the implementation in a code file. The header files, normally suffixed .h, are similar to C header files while the implementation (method) files, normally suffixed .m, can be very similar to C code files.

Interface

The interface of a class is usually defined in a header file. A common convention is to name the header file after the name of the class. The interface for class Ball would thus be found in the file Ball.h.

An interface declaration takes the form:

@interface classname : superclassname {
    // instance variables
}
+classMethod1;
+(return_type)classMethod2;
+(return_type)classMethod3:(param1_type)parameter_varName;

-(return_type)instanceMethod1:(param1_type)param1_varName :(param2_type)param2_varName;
-(return_type)instanceMethod2WithParameter:(param1_type)param1_varName andOtherParameter:(param2_type)param2_varName;
@end

In the above, plus signs denote class methods and minus signs denote instance methods. Class methods have no access to instance variables.

The code above is roughly equivalent to the following C++ interface:

class classname : superclassname {
 public:
  // instance variables

  // Class (static) functions
  static void* classMethod1();
  static return_type classMethod2();
  static return_type classMethod3(param1_type parameter_varName);

  // Instance (member) functions
  return_type instanceMethod1(param1_type param1_varName, param2_type param2_varName);
  return_type instanceMethod2WithParameter(param1_type param1_varName, param2_type param2_varName=default);
};

Note that instanceMethod2WithParameter demonstrates Objective-C's named parameter capability for which there is no direct equivalent in C/C++.

Return types can be any standard C type, a pointer to a generic Objective-C object, or a pointer to a specific type of object such as NSArray *, NSImage *, or NSString *. The default return type is the generic Objective-C type id.

Method arguments begin with a colon followed by the expected argument type in parentheses and the argument name. In some cases (e.g. when writing system APIs) it is useful to add descriptive text before each parameter.

-(void) setRangeStart:(int)start :(int)end;
-(void) importDocumentWithName:(NSString *)name withSpecifiedPreferences:(Preferences *)prefs beforePage:(int)insertPage;

Implementation

The interface only declares the class interface and not the methods themselves: the actual code is written in the implementation file. Implementation (method) files normally have the file extension .m.

@implementation classname
+classMethod {
    // implementation
}
-instanceMethod {
    // implementation
}
@end

Methods are written using their interface declarations. Comparing Objective-C and C:

-(int)method:(int)i {
    return [self square_root: i];
}
int function(int i) {
    return square_root(i);
}

The syntax allows pseudo-naming of arguments.

-(int)changeColorToRed:(float)red green:(float)green blue:(float)blue

[myColor changeColorToRed:5.0 green:2.0 blue:6.0];

Internal representations of a method vary between different implementations of Objective-C. If myColor is of the class Color, internally, instance method -changeColorToRed:green:blue: might be labeled _i_Color_changeColorToRed_green_blue. The i is to refer to an instance method, with the class and then method names appended, colons translated to underscores. As the order of parameters is part of the method name, it cannot be changed to suit coding style or expression as in true named parameters.

However, internal names of the function are rarely used directly. Generally, messages are converted to function calls defined in the Objective-C runtime library. It is not necessarily known at link time which method will be called because the class of the receiver (the object being sent the message) need not be known until runtime.

Instantiation

Once an Objective-C class is written, it can be instantiated. This is done by first allocating the memory for a new object and then by initializing it. An object isn't fully functional until both steps have been completed. These steps are typically accomplished with a single line of code:

MyObject * o = [[MyObject alloc] init];

Or, in Objective-C 2.0:

MyObject * o = [MyObject new];

The alloc call allocates enough memory to hold all the instance variables for an object, and the init call can be overridden to set instance variables to specific values on creation. The init method is often written as follows:

-(id) init {
    if ( self = [super init] ) {
        ivar1 = value1;
        ivar2 = value2;
        .
        .
        .
    }
    return self;
}

In the above example, remark the id return type. This is the type of any object in Objective-C (See #Dynamic typing)

Protocols

Objective-C was extended at NeXT to introduce the concept of multiple inheritance of specification, but not implementation, through the introduction of protocols. This is a pattern achievable either as an abstract multiply-inherited base class in C++, or as an "interface" (as in Java and C#). Objective-C makes use of ad-hoc protocols called informal protocols and compiler enforced protocols called formal protocols.

An informal protocol is a list of methods which a class can opt to implement. It is specified in the documentation, since it has no presence in the language. Informal protocols often include optional methods, where implementing the method can change the behavior of a class. For example, a text field class might have a delegate which should implement an informal protocol with an optional autocomplete method. The text field discovers whether the delegate implements that method (via reflection), and, if so, calls it to support autocomplete.

A formal protocol is similar to an interface in Java or C#. It is a list of methods which any class can declare itself to implement. Versions of Objective-C before 2.0 required that a class must implement all methods in a protocol it declares itself as adopting; the compiler will emit an error if the class does not implement every method of its declared protocols. Objective-C 2.0 added support for marking certain methods in a protocol optional, and the compiler will not enforce implementation of optional methods.

The Objective-C concept of protocols is different from the Java or C# concept of interfaces in that a class may implement a protocol without being declared to implement that protocol. The difference is not detectable from outside code. Formal protocols cannot provide any implementations, they simply assure callers that classes which conform to the protocol will provide implementations. In the NeXT/Apple library, protocols are frequently used by the Distributed Objects system to represent the capabilities of an object executing on a remote system.

The syntax

@protocol Locking
- (void)lock;
- (void)unlock;
@end

denotes that there is the abstract idea of locking. By stating that the protocol is implemented in the class definition:

@interface SomeClass : SomeSuperClass <Locking>
@end

instances of SomeClass claim that they will provide an implementation for the two instance methods using whatever means they choose. Another example use of abstract specification is describing the desired behaviors of plug-ins without constraining what the implementation hierarchy should be.

Dynamic typing

Objective-C, like Smalltalk, can use dynamic typing: an object can be sent a message that is not specified in its interface. This can allow for increased flexibility, as it allows an object to "capture" a message and send the message to a different object who can respond to the message appropriately, or likewise send the message on again. This behavior is known as message forwarding or delegation (see below). Alternatively, an error handler can be used in case the message cannot be forwarded. If an object does not forward a message, respond to it, or handle an error, the message is silently discarded; this is true even if messages are sent to nil (the null object pointer).

Static typing information may also optionally be added to variables. This information is then checked at compile time. In the following three statements, increasingly specific type information is provided. The statements are equivalent at runtime, but the additional information allows the compiler to warn the programmer if the passed argument does not match the type specified.

- setMyValue:(id) foo;

In the above statement, the object may be of any class.

- setMyValue:(id <aProtocol>) foo;

In the above statement, the object may still be an instance of any class but the class must conform to the aProtocol protocol.

- setMyValue:(NSNumber*) foo;

In the above statement, foo must be a member of the NSNumber class.

Dynamic typing can be a powerful feature. When implementing container classes using statically-typed languages without generics (like Java prior to version 5), the programmer is forced to write a container class for a generic type of object, and then cast back and forth between the abstract generic type and the real type. Casting, however, breaks the discipline of static typing. For instance, putting in an Integer and reading out a String will produce a runtime error. This problem is addressed in, for example, Java 5 and C# with generic programming, but then container classes must be homogeneous in type. This need not be the case with dynamic typing.

Forwarding

Objective-C permits the sending of a message to an object that may not respond. Rather than responding or simply dropping the message, an object can forward the message to an object which can respond. Forwarding can be used to simplify implementation of certain design patterns, such as the Observer pattern or the Proxy pattern.

The Objective-C runtime specifies a pair of methods in Object

  • forwarding methods:
- (retval_t) forward:(SEL) sel :(arglist_t) args; // with GCC
- (id) forward:(SEL) sel :(marg_list) args; // with NeXT/Apple systems
  • action methods:
- (retval_t) performv:(SEL) sel :(arglist_t) args;  // with GCC
- (id) performv:(SEL) sel :(marg_list) args; // with NeXT/Apple systems

An object wishing to implement forwarding needs only to override the forwarding method to define the forwarding behavior. The action methods performv:: need not be overridden as this method merely performs action based on the selector and arguments. Notice the SEL type, which is the type of messages in Objective-C.

Example

Here is an example of a program which demonstrates the basics of forwarding.

Forwarder.h
#import <objc/Object.h>
 
@interface Forwarder : Object
{
    id recipient; //The object we want to forward the message to. 
}
 
//Accessor methods
- (id) recipient;
- (id) setRecipient:(id) _recipient; 
 
@end
Forwarder.m
#import "Forwarder.h"

@implementation Forwarder

- (retval_t) forward: (SEL) sel : (arglist_t) args
{
    /*
     * Check whether the recipient actually responds to the message. 
     * This may or may not be desirable, for example, if a recipient
     * in turn does not respond to the message, it might do forwarding
     * itself.
     */
    if([recipient respondsTo:sel]) 
       return [recipient performv: sel : args];
    else
       return [self error:"Recipient does not respond"];
}

- (id) setRecipient: (id) _recipient
{
    recipient = _recipient;
    return self;
}

- (id) recipient
{
    return recipient;
}
@end
Recipient.h
#import <objc/Object.h>
 
// A simple Recipient object.
@interface Recipient : Object
- (id) hello;
@end
Recipient.m
#import "Recipient.h"

@implementation Recipient

- (id) hello
{
    printf("Recipient says hello!\n");

    return self;
}

@end
main.m
#import "Forwarder.h"
#import "Recipient.h"

int main(void)
{
    Forwarder *forwarder = [Forwarder new];
    Recipient *recipient = [Recipient new];

    [forwarder setRecipient:recipient]; //Set the recipient. 
    /* 
     * Observe forwarder does not respond to a hello message! It will
     * be forwarded. All unrecognized methods will be forwarded to
     * the recipient 
     * (if the recipient responds to them, as written in the Forwarder)
     */
    [forwarder hello]; 

    return 0;
}

Notes

When compiled using gcc, the compiler reports:

$ gcc -x objective-c -Wno-import Forwarder.m Recipient.m main.m -lobjc
main.m: In function `main':
main.m:12: warning: `Forwarder' does not respond to `hello'
$

The compiler is reporting the point made earlier, that Forwarder does not respond to hello messages. In this circumstance, it is safe to ignore the warning since forwarding was implemented. Running the program produces this output:

$ ./a.out
Recipient says hello!

Categories

The maintainability of large code bases was one of the main concerns during the design of Objective-C. Experience from the structured programming world had shown that one of the main ways to improve code was to break it down into smaller pieces. Objective-C borrowed and extended the concept of Categories to help with this process from Smalltalk implementations (e.g., see [5]).

A category collects method implementations into separate files. The programmer can place groups of related methods into a category to make them more readable. For instance, one could create a "SpellChecking" category "on" the String object, collecting all of the methods related to spell checking into a single place.

Furthermore, the methods within a category are added to a class at runtime. Thus, categories permit the programmer to add methods to an existing class without the need to recompile that class or even have access to its source code. For example, if a system does not contain a spell checker in its String implementation, it could be added without modifying the String source code.

Methods within categories become indistinguishable from the methods in a class when the program is run. A category has full access to all of the instance variables within the class, including private variables.

Categories provide an elegant solution to the fragile base class problem for methods.

If a category declares a method with the same method signature as an existing method in a class, the category’s method is adopted. Thus categories can not only add methods to a class, but also replace existing methods. This feature can be used to fix bugs in other classes by rewriting their methods, or to cause a global change to a class’ behavior within a program. If two categories have methods with the same method signature, it is undefined which category’s method is adopted.

Other languages have attempted to add this feature in a variety of ways. TOM took the Objective-C system a step further and allowed for the addition of variables as well. Other languages have instead used prototype oriented solutions, the most notable being Self.

The C# and Visual Basic.NET languages implement similar functionality in the form of Extension Methods and partial classes.

Example usage of categories

This example builds up an Integer class, by defining first a basic class with only accessor methods implemented, and adding two categories, Arithmetic and Display, which extend the basic class. While categories can access the base class’ private data members, it is often good practice to access these private data members through the accessor methods, which helps keep categories more independent from the base class. This is one typical usage of categories—the other is to use categories to add or replace certain methods in the base class (however it is not regarded as good practice to use categories for subclass overriding, also known as monkey patching).

Integer.h
#import <objc/Object.h>

@interface Integer : Object
{
    int integer;
}

- (int) integer;
- (id) integer: (int) _integer;
@end
Integer.m
#import "Integer.h"

@implementation Integer
- (int) integer
{
    return integer;
}

- (id) integer: (int) _integer
{
    integer = _integer;

    return self;
}
@end
Arithmetic.h
#import "Integer.h"

@interface Integer (Arithmetic)
- (id) add: (Integer *) addend;
- (id) sub: (Integer *) subtrahend;
@end
Arithmetic.m
#import "Arithmetic.h"

@implementation Integer (Arithmetic) 
- (id) add: (Integer *) addend
{
    return [self integer: [self integer] + [addend integer]];
}

- (id) sub: (Integer *) subtrahend
{
    return [self integer: [self integer] - [subtrahend integer]];
}
@end
Display.h
#import "Integer.h"

@interface Integer (Display)
- (id) showstars;
- (id) showint;
@end
Display.m
#import "Display.h"

@implementation Integer (Display) 
- (id) showstars
{
    int i, x = [self integer];
    for(i=0; i < x; i++)
       printf("*");
    printf("\n");

    return self;
}

- (id) showint
{
    printf("%d\n", [self integer]);

    return self;
}
@end
main.m
#import "Integer.h"
#import "Arithmetic.h" 
#import "Display.h"

int
main(void)
{
    Integer *num1 = [Integer new], *num2 = [Integer new];
    int x;
    printf("Enter an integer: ");
    scanf("%d", &x);
    [num1 integer:x];
    [num1 showstars];
    printf("Enter an integer: ");
    scanf("%d", &x);
    [num2 integer:x];
    [num2 showstars];

    [num1 add:num2];
    [num1 showint];

    return 0;
}

Notes

Compilation is performed, for example, by

gcc -x objective-c main.m Integer.m Arithmetic.m Display.m -lobjc

One can experiment by omitting the #import "Arithmetic.h" and [num1 add:num2] lines and omit Arithmetic.m in compilation. The program will still run. This means that it is possible to "mix-and-match" added categories if necessary – if one does not need to have some capability provided in a category, one can simply not compile it in.

Posing

Objective-C permits a class to wholly replace another class within a program. The replacing class is said to "pose as" the target class.

Note: Class posing was declared deprecated with Mac OS X v10.5 and unavailable in the 64-bit runtime.

For the versions still supporting posing, all messages sent to the target class are instead received by the posing class. There are several restrictions:

  • A class may only pose as one of its direct or indirect superclasses
  • The posing class must not define any new instance variables which are absent from the target class (though it may define or override methods).
  • The target class may not have received any messages prior to the posing.

Posing, similarly to categories, allows global augmentation of existing classes. Posing permits two features absent from categories:

  • A posing class can call overridden methods through super, thus incorporating the implementation of the target class.
  • A posing class can override methods defined in categories.

For example,

@interface CustomNSApplication : NSApplication
@end

@implementation CustomNSApplication
- (void) setMainMenu: (NSMenu*) menu
{
     // do something with menu
}
@end

class_poseAs ([CustomNSApplication class], [NSApplication class]);

This intercepts every invocation of setMainMenu to NSApplication.

#import

In the C language, the #include pre-compile directive always causes a file's contents to be inserted into the source at that point. Objective-C has the equivalent #import directive except each file is included only once per compilation unit.

Other features

Objective-C's features often allow for flexible, and often easy, solutions to programming issues.

  • Delegating methods to other objects and remote invocation can be easily implemented using categories and message forwarding.
  • Swizzling of the isa pointer allows for classes to change at runtime. Typically used for debugging where freed objects are swizzled into zombie objects, whose only purpose is to report an error when someone calls them. Swizzling was also used in EOF to create database faults. Swizzling is used today by Apple’s Foundation Framework to implement Key-Value Observing.
  • Serialization, commonly called Archiving in Objective-C, can be done by overriding read and write methods.

Language variants

Objective-C++

Objective-C++ is a front-end to the GNU Compiler Collection which can compile source files which use a combination of C++ and Objective-C syntax. Objective-C++ adds to C++ the extensions Objective-C adds to C. As nothing is done to unify the semantics behind the various language features, certain restrictions apply:

  • A C++ class cannot derive from an Objective-C class and vice versa.
  • C++ namespaces cannot be declared inside an Objective-C declaration.
  • Objective-C classes cannot have instance variables of C++ classes which do not have a default constructor or which have one or more virtual methods, but pointers to C++ objects can be used as instance variables without restriction (allocate them with new in the -init method).
  • C++ "by value" semantics cannot be applied to Objective-C objects, which are only accessible through pointers.
  • An Objective-C declaration cannot be within a C++ template declaration and vice versa. However, Objective-C types, (e.g., Classname *) can be used as C++ template parameters.
  • Objective-C and C++ exception handling is distinct; the handlers of each cannot handle exceptions of the other type.
  • Care must be taken since the destructor calling conventions of Objective-C and C++’s exception run-time models do not match (i.e., a C++ destructor will not be called when an Objective-C exception exits the C++ object’s scope). The new 64-bit runtime resolves this by introducing interoperability with C++ exceptions in this sense.[6]

Objective-C 2.0

At the 2006 Worldwide Developers Conference, Apple announced the forthcoming release of "Objective-C 2.0," a revision of the Objective-C language to include "modern garbage collection, syntax enhancements[7], runtime performance improvements[8], and 64-bit support". Mac OS X v10.5, released in October 2007, included an Objective-C 2.0 compiler. It is not yet known when these language changes will be available in the GNU runtime, or if they will all be implemented to be compliant with the whole Objective-C 2.0 standard.

Garbage collection

Objective-C 2.0 provides an optional conservative yet generational garbage collector. When run in backwards-compatible mode, the runtime turns reference counting operations such as "retain" and "release" into no-ops. All objects are subject to garbage collection when garbage collection is enabled. Regular C pointers may be qualified with "__strong" to also trigger the underlying write-barrier compiler intercepts and thus participate in garbage collection. A zero-ing weak subsystem is also provided such that pointers marked as "__weak" are set to zero when the object (or more simply, GC memory) is collected. The garbage collector does not exist on the iPhone implementation of Objective-C 2.0. Garbage Collection in Objective-C runs on a low-priority background thread, and can halt on user events, with the intention of keeping the user experience responsive.[9]

Properties

Objective-C 2.0 introduces a new syntax to declare instance variables as properties, with optional attributes to configure the generation of accessor methods. Properties are, in a sense, public instance variables; that is, declaring an instance variable as a property provides external classes with access (possibly limited, e.g. readonly) to that property. A property may be declared as "readonly", and may be provided with storage semantics such as "assign", "copy" or "retain". By default, properties are considered atomic, which results in a lock preventing multiple threads from accessing them at the same time. A property can be declared as "nonatomic" which removes this lock.

@interface Person : NSObject {
 @public
    NSString *name;
 @private
    int age;
}
@property(copy) NSString *name;
@property(readonly) int age;
-(id)initWithAge:(int)age;
@end

Properties are implemented by way of the @synthesize keyword, which generates getter and setter methods according to the property declaration. Alternately, the @dynamic keyword can be used to indicate that accessor methods will be provided by other means.

@implementation Person
@synthesize name;
@dynamic age;
-(id)initWithAge:(int)initAge
{
    age = initAge; // NOTE: direct instance variable assignment, not property setter
    return self;
}
-(int)age
{
    return 29; // NOTE: lying about age
}
@end

Properties can be accessed using the traditional message passing syntax, dot notation, or by name via the "valueForKey:"/"setValue:forKey:" methods.

Person *aPerson = [[Person alloc] initWithAge: 53];
aPerson.name = @"Steve"; // NOTE: dot notation, uses synthesized setter, equivalent to [aPerson setName: @"Steve"];
NSLog(@"Access by message (%@), dot notation(%@), property name(%@) and direct instance variable access (%@)",
      [aPerson name], aPerson.name, [aPerson valueForKey:@"name"], aPerson->name);

In order to use dot notation to invoke property accessors within an instance method, the "self" keyword should be used:

-(void) introduceMyselfWithProperties:(BOOL)useGetter
{
    NSLog(@"Hi, my name is %@.", (useGetter ? self.name : name)); // NOTE: getter vs. ivar access
}

A class or protocol's properties may be dynamically introspected.

int i, propertyCount = 0;
objc_property_t *propertyList = class_copyPropertyList([aPerson class], &propertyCount);
for (i=0; i<propertyCount; i++) {
    objc_property_t *thisProperty = propertyList + i;
    const char* propertyName = property_getName(*thisProperty);
    NSLog(@"Person has a property: '%s'", propertyName);
}

Non-fragile instance variables

Objective-C 2.0 provides non-fragile instance variables where supported by the runtime (i.e. when building 64-bit Mac OS X code as well as all iPhone OS code). Under the modern runtime, an extra layer of indirection is added to instance variable access, allowing the dynamic linker to adjust instance layout at runtime. This feature allows for two important improvements to Objective-C code:

  • This eliminates the fragile binary interface problem - Superclasses can change sizes without affecting binary compatibility.
  • This allows instance variables that provide the backing for properties to be synthesized at runtime without them being declared in the class’ interface.

Fast enumeration

Instead of using an NSEnumerator object or indices to iterate through a collection, Objective-C 2.0 offers the fast enumeration syntax. In Objective-C 2.0, the following loops are functionally equivalent, but have different performance characteristics.

// Using NSEnumerator
NSEnumerator *enumerator = [thePeople objectEnumerator];
Person *p;
while ((p = [enumerator nextObject]) != nil) {
    NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// Using indices
for (int i=0; i<[thePeople count]; i++) {
    Person *p = [thePeople objectAtIndex:i];
    NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// Using fast enumeration
for (Person *p in thePeople)
    NSLog(@"%@ is %i years old.", [p name], [p age]);

Fast enumeration generates more efficient code than standard enumeration because method calls to enumerate over objects are replaced by pointer arithmetic using the NSFastEnumeration protocol.[10]

Implications for Cocoa development

All Objective-C applications developed for Mac OS X that make use of the above improvements for Objective-C 2.0 are incompatible with all operating systems prior to 10.5 (Leopard). Even using fast enumeration, which one might expect to generate the exact same binaries as standard enumeration, will cause an application to crash on OS X version 10.4 or earlier.

Today

Objective-C today is often used in tandem with a fixed library of standard objects (often known as a "kit" or "framework"), such as Cocoa or GNUstep. These libraries often come with the operating system: the GNUstep libraries often come with Linux distributions and Cocoa comes with Mac OS X. The programmer is not forced to inherit functionality from the existing base class (NSObject). Objective-C allows for the declaration of new root classes which do not inherit any existing functionality. Originally, Objective-C based programming environments typically offered an Object class as the base class from which almost all other classes inherited. With the introduction of OpenStep, NeXT created a new base class named NSObject which offered additional features over Object (an emphasis on using object references and reference counting instead of raw pointers, for example). Almost all classes in Cocoa inherit from NSObject.

Not only did the renaming serve to differentiate the new default behavior of classes within the OpenStep API, but it allowed code which used Object — the original base class used on NeXTSTEP (and, more or less, other Objective-C class libraries) — to co-exist in the same runtime with code which used NSObject (with some limitations). As well, the introduction of the two letter prefix became a sort of simplistic form of namespaces, which Objective-C lacks. Using a prefix to create an informal packaging identifier became an informal coding standard in the Objective-C community, and continues to this day.

Portable Object Compiler

Besides the GCC/NeXT/Apple implementation, which added several extensions to the original Stepstone implementation, another free, open-source Objective-C implementation called The Portable Object Compiler[11] also exists. The set of extensions implemented by The Portable Object Compiler differs from the GCC/NeXT/Apple implementation in the extensions it includes. In particular, it includes Smalltalk-like blocks for Objective-C.

Analysis of the language

Objective-C implementations use a thin runtime written in C which adds little to the size of the application. In contrast, most OO systems at the time that it was created used large virtual machine runtimes. Programs written in Objective-C tend to be not much larger than the size of their code and that of the libraries (which generally do not need to be included in the software distribution), in contrast to Smalltalk systems where a large amount of memory was used just to open a window. Objective-C applications tend to be larger than similar C or C++ applications because Objective-C dynamic typing does not allow methods to be stripped or inlined.

Likewise, the language can be implemented on top of existing C compilers (in GCC, first as a preprocessor, then as a module) rather than as a new compiler. This allows Objective-C to leverage the huge existing collection of C code, libraries, tools, and mindshare. Existing C libraries can be wrapped in Objective-C wrappers to provide an OO-style interface.

All of these practical changes lowered the barrier to entry, likely the biggest problem for the widespread acceptance of Smalltalk in the 1980s.

The first versions of Objective-C did not support garbage collection. At the time this decision was a matter of some debate, and many people considered long "dead times" (when Smalltalk did collection) to render the entire system unusable. Some 3rd party implementations have added this feature (most notably GNUstep) and Apple has implemented it as of Mac OS X v10.5.[12]

Another common criticism is that Objective-C does not have language support for namespaces. Instead, programmers are forced to add prefixes to their class names, which are traditionally shorter than namespace names and thus more prone to collisions. As of 2007, all Mac OS X classes and functions in the Cocoa programming environment are prefixed with "NS" (e.g. NSObject, NSButton) to identify them as belonging to the Mac OS X core; the "NS" derives from the names of the classes as defined during the development of NeXTstep.

Since Objective-C is a strict superset of C, it does not treat C primitive types as first-class objects either.

Unlike C++, Objective-C does not support operator overloading. Also unlike C++, Objective-C allows an object to directly inherit only from one class (forbidding multiple inheritance). However, categories and protocols may be used as alternative functionality to multiple inheritance.

Because Objective-C uses dynamic runtime typing and because all method calls are function calls (or, in some cases, syscalls), many common performance optimizations cannot be applied to Objective-C methods (for example: inlining, constant propagation, interprocedural optimizations, and scalar replacement of aggregates). This limits the performance of Objective-C abstractions relative to similar abstractions in languages such as C++ where such optimizations are possible.

Philosophical differences between Objective-C and C++

The design and implementation of C++ and Objective-C represent different approaches to extending C.

In addition to C’s style of procedural programming, C++ directly supports object-oriented programming, generic programming, and metaprogramming. C++ also comes with a large standard library which includes several container classes. Objective-C, on the other hand, adds only object-oriented features to C. Objective-C in its purest fashion does not contain the same number of standard library features, but in most places where Objective-C is used, it is used with an OpenStep-like library such as OPENSTEP, Cocoa, or GNUstep which provide similar functionality to some of C++’s standard library.

One notable difference is that Objective-C provides runtime support for some reflective features, whereas C++ adds only a small amount of runtime support to C. In Objective-C, an object can be queried about its own properties, for example whether it will respond to a certain message. In C++ this is not possible without the use of external libraries.

The use of reflection is part of the wider distinction between dynamic (run-time) features versus static (compile-time) features of a language. Although Objective-C and C++ each employ a mix of both features, Objective-C is decidedly geared toward run-time decisions while C++ is geared toward compile-time decisions. The tension between dynamic and static programming involves many of the classic trade-offs in programming.

See also

Notes

References

  • Cox, Brad J. (1991). Object Oriented Programming: An Evolutionary Approach. Addison Wesley. ISBN 0-201-54834-8. 

External links

bn:অবজেক্টিভ সি bg:Objective-C cs:Objective-C da:Objective-C de:Objective-C es:Objective-C eo:Objective-C fa:آبجکتیو-سی fr:Objective-C gl:Objective-C ko:오브젝티브-C it:Objective C ka:Objective-C hu:Objective-C nl:Objective-C ja:Objective-C no:Objective-C pl:Objective-C pt:Objective-C ru:Objective-C simple:Objective-C sk:Objective-C fi:Objective-C sv:Objective-C th:ภาษาอ็อบเจกทีฟ-ซี tg:Objective-C tr:Objective-C uk:Objective C zh:Objective-C

If you like SEOmastering Site, you can support it by - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 and more...