'language'에 해당되는 글 1건

  1. 2010.06.24 The Objective-C 2.0 Programming Language
오브젝트C2010. 6. 24. 14:13
The Objective-C 2.0 Programming Language
Ch1. Objects, Classes, and Messaging

In Objective-C, it is valid to send a message to nil - it simply has no effect at runtime and returns nil.


A crucial difference between function calls and messages is that a function and its arguments are joined together in the compiled code, but a message and a receiving object aren’t united until the program is running and the message is sent. Therefore, the exact method that’s invoked to respond to a message can only be determined at runtime, not when the code is compiled.


Objective-C provides a dot (.) operator that offers a compact and convenient syntax you can use as an alternative to square bracket notation ([]s) to invoke accessor methods.

Despite appearances to the contrary, the dot syntax therefore preserves encapsulation—you are not accessing an instance variable directly.


If you want to access a property of self using accessor methods, you must explicitly call out self


class object -> class instance

A class that doesn’t need to inherit any special behavior from another class should nevertheless be made a subclass of the NSObject class.

myRectangle = [[Rectangle alloc] init];

Every class object has at least one method (like alloc)that enables it to produce new objects, and every instance has at least one method (like init) that prepares it for use.


Unlike C++, there is no static class member variable, instead you should define static variable in the@implementation file.


class method vs. instance method?

The runtime system sends an initialize message to every class object before the class receives any other messages and after its superclass has received the initialize message.


When a class object receives a message that it can’t respond to with a class method, the runtime system determines whether there’s a root instance method that can respond.


The class name can stand for the class object only as a message receiver.

ex) [anObject isKindOfClass:[Rectangle class]]

It would have been illegal to simply use the name “Rectangle” as the argument.


class equality test

[objectA class] == [objectB class]


Ch2. Defining a Class

+ class method

- instance method

If a return or argument type isn’t explicitly declared, it’s assumed to be the default type for methods and messages — an id.


#import directive is identical to #include, except that it makes sure that the same file is never included more than once.


@class Rectangle, Circle;

The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name.


** typical interface (.h file) **

#import "ItsSuperclass.h"

@interface ClassName : ItsSuperclass

{

    instance variable declarations

}

method declarations

@end


** typical implementation (.m file) **

@implementation ClassName : ItsSuperclass

{

    instance variable declarations

}

method definitions

@end


** simple implementation by importing header file **

#import "ClassName.h"

@implementation ClassName

method definitions

@end


By default, all unmarked instance variables are @protected. (private in C++ class, public in C++ struct)


self - class of the object that is sending message. If it is called in a inherited method, self is the class of the derived object.

super - class above the class where the method is defined.


Ch3. Allocating and Initializing Objects

Because an init... method might return an object other than the newly allocated receiver, or even return nil, it’s important that programs use the value returned by the initialization method.


** dangerous **

id anObject = [SomeClass alloc];

[anObject init];

[anObject someOtherMessage];

** safe **

id anObject = [[SomeClass alloc] init];

[anObject someOtherMessage];

-- or --

id anObject = [[SomeClass alloc] init];

if ( anObject )// check for nil is needed.

    [anObject someOtherMessage];

else

    ...


In general, if there is a problem during an initialization method, you should call [self release] and return nil.

You should only call [self release] at the point of failure. If you get nil back from an invocation of the super class’s initializer, you should not also callrelease.


You should typically not use exceptions to signify errors of initializer.


General Principle:The designated initializer in a class must,through a message to super, invoke the designated initializer in a superclass.


Ch4. Declared Properties

@interface MyClass : NSObject

{

    NSString *value;

}

@property(copy, readwrite) NSString *value;

@end

---

@implementation MyClass

@synthesize value;

@end

---

@synthesize age = yearsOld; // accessor: age, instance variable: yearsOld


When you synthesize a property, the compiler only creates any absent accessor methods.


attributes = (readwrite | readonly) | (assign | retain | copy) | (nonautomic) | (setter=) | (getter=)


You cannot specify the retain attribute for non-objecttypes.


informal decorator = (IBOutlet) | (__weak | __strong)


With @dynamic, you notify the compiler that you would provide the methods.


// assume using garbage collection

@implementation MyClass

@dynamic value;

- (NSString *)value {

    return value;

}

- (void)setValue:(NSString *)newValue {

    if (newValue != value) {

        value = [newValue copy];

    }

}

@end


You can re-declare a property in a subclass, but (with the exception of readonly vs. readwrite) you must repeat its attributes in whole in the subclasses.

If you declare a property in one classas readonly, you can redeclare it as readwrite in a class extension.

- a mutable subclass of an immutable class

- read only in public API, readwrite in private implentation file


the copy method returns an immutable version of the collection. You have to provide your own setter to set mutable object property.


@interface MyClass : NSObject {

    NSMutableArray *myArray;

}

@property (nonatomic, copy) NSMutableArray *myArray;

@end


@implementation MyClass

@synthesize myArray;

- (void)setMyArray:(NSMutableArray *)newArray {

    if (myArray != newArray) {

        [myArray release];

        myArray = [newArray mutableCopy];

    }

}

@end


You can look for all the property declarations in your header file and make sure that object properties not marked assign are released, and those marked assign are not released.


You should use invoke the accessor method on modern runtime.


- (void)dealloc {

    [self setProperty:nil];

    [super dealloc];

}


** property declaration meaning **

// assign

property = newValue;

// retain

if (property != newValue) {

    [property release];

    property = [newValue retain];

}

// copy

if (property != newValue) {

    [property release];

    property = [newValue copy];

}

// atomic

[_internal lock]; // lock using an object-level lock

id result = [[value retain] autorelease];

[_internal unlock];

return result;


Simply making all the properties in your class atomic does not mean that your class or more generally your object graph is “thread safe”.


The modern runtime supports instance variable synthesis whereas the legacy runtime does not.


Ch5. Categories and Extensions

A category allows you to add methods to an existing class—even to one to which you do not have the source.

Class extensions are similar, but allow additional required API to be declared for a class in locations other than within the primary class @interface block.


Category methods can do anything that methods defined in the class proper can do. At runtime, there’s no difference. The methods the category adds to the class are inherited by all the class’s subclasses, just like other methods.


#import "ClassName.h"

@interface ClassName ( CategoryName )

// method declarations

@end


A category implementation (in a file named ClassName+CategoryName.m) might therefore look like this:


#import "ClassName+CategoryName.h"

@implementation ClassName ( CategoryName )

// method definitions

@end


Normally, class objects can perform only class methods. But instance methods defined in the root class are a special case.


Class extensions are like “anonymous” categories, except that the methods they declare must be implemented in the main @implementation block for the corresponding class.


Ch6. Protocols

A protocol is simply a list of method declarations, unattached to a class definition.


@protocol MyXMLSupport

- initFromXMLRepresentation:(NSXMLElement *)XMLElement;

@property (nonatomic, readonly) (NSXMLElement *)XMLRepresentation;

@end


Unlike class names, protocol names don’t have global visibility. They live in their own namespace.


The default is @required.

@protocol MyProtocol

- (void)requiredMethod;

@optional

- (void)anOptionalMethod;

- (void)anotherOptionalMethod;

@required

- (void)anotherRequiredMethod;

@end


** On Mac OS X v10.5, protocols may not include optional declared properties.


** sender **

Source code can refer to a Protocol object using the @protocol() directive.

Protocol *myXMLSupportProtocol = @protocol(MyXMLSupport);


** receiver **

Adopting a formal protocol:

@interface ClassName : ItsSuperclass < protocol list >

Categories adopt protocols in much the same way:

@interface ClassName ( CategoryName ) < protocol list >


A class is said to conform to a formal protocol if it adopts the protocol or inherits from another class that adopts it.

if (![receiver conformsToProtocol:@protocol(MyXMLSupport)]) {...


conformsToProtocol: is both class and instance method.


Protocols can’t be used to type class objects. Only instances can be statically typed to a protocol, just as only instances can be statically typed to a class.


One protocol can incorporate other protocols:

@protocol ProtocolName < protocol list >


A class can conform to a protocol without formally adopting it simply by implementing the methods declared in the protocol.


circular dependency between protocols (x) -> forward reference (o)

@protocol B;

@protocol A

- foo:(id <B>) anObject;

@end


Ch7.Fast Enumeration

for ( Type newVariable in expression ) { statements }

: expression should adopt NSFastEnumeration protocol.


Since mutation of the object during iteration is forbidden, you can perform multiple enumerations concurrently.


Ch8. Enabling Static Behavior

Static typing also doesn’t affect how the object is treated at runtime. Messages sent to statically typed objects are dynamically bound, just as objects typed id are.Static typing allows for compile-time type checking.


Methods in different classes that have the same selector must also share the same return and argument types.


Ch9. Selectors

Compiled selectors are assigned to a special type, SEL.

The @selector() directive lets you refer to the compiled selector.

SEL setWidthHeight;

setWidthHeight = @selector(setWidth:height:);


To convert a character string to a selector at runtime:

setWidthHeight = NSSelectorFromString(aBuffer);


Conversion in the opposite direction is also possible:

NSString *method;

method = NSStringFromSelector(setWidthHeight);


Compiled selectors identify method names, not method implementations. It lets you send the same message to receivers belonging to different classes.


Except for messages sent to statically typed receivers, dynamic binding requires all implementations of identically named methods to have the same return type and the same argument types.


[friend performSelector:@selector(gossipAbout:)withObject:aNeighbor];

is equivalent to:

[friend gossipAbout:aNeighbor];


The receiver and message can vary at runtime:

id      helper = getTheReceiver();

SEL    request = getTheSelector();

[helper performSelector:request];


Ch10. Exception Handling

Just like the C++ / Java language.

@try {

    ...

}

@catch (CustomException *ce) {// 1

    ...

}

@catch (NSException *ne) {// 2

    // Perform processing necessary at this level.

    ...

}

@catch (id ue) {

    ...

}

@finally {// 3

    // Perform processing necessary whether an exception occurredor not.

    ...

}


** Throwing exceptions **

NSException *exception = [NSException exceptionWithName:@"HotTeaException"reason:@"The tea is too hot"userInfo:nil];

@throw exception;


Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors.

Inside a @catch()block, you can re-throw the caught exception using the @throw directive without an argument.


Ch11. Threading

To turn on support for thread sync. and exception handling, use the -fobjc-exceptions switch. Itrenders the application runnable only in Mac OS X v10.3 and later.


The @synchronized() directive takes as its only argument any Objective-C object, including self.

- (void)criticalMethod

{

    @synchronized(self) {

        // Critical code.

        ...

    }

}

When code in an @synchronized() block throws an exception, the Objective-C runtime catches the exception, releases the semaphore (so that the protected code can be executed by other threads), and re-throws the exception to the next exception handler.


Ch12. Remote Messaging

A remote receiver is typically anonymous.an object that’s designated to receive remote messages advertises its inter face in a formal protocol.


// asynchronous

- (oneway void)waltzAtWill;         

// information is being passed in a message 

- setTune:(in struct tune *)aSong;

// an argument is being used to return information by reference

- getTune:(out struct tune *)theSong;

// an argument is used both to provide information and to get  information back

- adjustTune:(inout struct tune *)aSong;

// composite value, not a simple pointer

- getTuneTitle:(out char **)theTitle;

// send an object, not a proxy

- danceWith:(bycopy id)aClone;

// objects passed or returned by reference

byref


Ch13. C++ with ObjC

You can include pointers to Objective-C objects as data members of C++ classes, and you can include pointers to C++ objects as instance variables of Objective-C classes.

Xcode requires that file names have a “.mm” extension for the Objective-C++ extensions to be enabled by the compiler.


C++ classes defined within an Objective-C interface are globally-scoped, not nested within the Objective-C class.

C++ classes that have virtual member function cannot serve as an ObjC instance variable.


** preprocessor constants **

__cplusplus

__OBJC__


Objective-C++ does not allow you to inherit C++ classes from Objective-C objects, nor does it allow you to inherit Objective-C classes from C++ objects. The layout of Objective-C and C++ objects in memory is mutually incompatible.


Objective-C does not have a notion of nested namespaces. You cannot declare Objective-C classes within C++ namespaces, nor can you declare namespaces within Objective-C classes.


Objective-C classes, protocols, and categories cannot be declared inside a C++ template, nor can a C++ template be declared inside the scope of an Objective-C interface, protocol, or category.


However, Objective-C classes may serve as C++ template parameters. C++ template parameters can also be used as receivers or parameters (though not as selectors) in Objective-C message expressions.


You cannot use Objective-C syntax to call a C++ object, you cannot add constructors or destructors to an Objective-C object.


An exception thrown in Objective-C code cannot be caught in C++ code and, conversely, an exception thrown in C++ code cannot be caught in Objective-C code.



출처 : http://blog.naver.com/PostView.nhn?blogId=gonagi&logNo=150045911302

'오브젝트C' 카테고리의 다른 글

Object-C : Declared Properties 에 대한 깔끔한 정리  (0) 2010.08.12
Hello iPhone - 1  (0) 2010.08.11
The Objective-C 2.0 Programming Language  (0) 2010.06.24
Objective-C  (0) 2010.06.22
Objective-C의 기본 문법  (0) 2010.06.22
Objective-C의 특징  (0) 2010.06.22
Posted by 오늘마감

댓글을 달아 주세요