![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /usr/share/doc/gnustep-base-doc/Base/ProgrammingManual/gs-base/ |
Upload File : |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <!-- Created by GNU Texinfo 6.7, http://www.gnu.org/software/texinfo/ --> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Classes (Objective-C GNUstep Base Programming Manual)</title> <meta name="description" content="Classes (Objective-C GNUstep Base Programming Manual)"> <meta name="keywords" content="Classes (Objective-C GNUstep Base Programming Manual)"> <meta name="resource-type" content="document"> <meta name="distribution" content="global"> <meta name="Generator" content="makeinfo"> <link href="index.html" rel="start" title="Top"> <link href="Make.html" rel="index" title="Make"> <link href="index.html#SEC_Contents" rel="contents" title="Table of Contents"> <link href="index.html" rel="up" title="Top"> <link href="Advanced-Messaging.html" rel="next" title="Advanced Messaging"> <link href="Objects.html" rel="prev" title="Objects"> <style type="text/css"> <!-- a.summary-letter {text-decoration: none} blockquote.indentedblock {margin-right: 0em} div.display {margin-left: 3.2em} div.example {margin-left: 3.2em} div.lisp {margin-left: 3.2em} kbd {font-style: oblique} pre.display {font-family: inherit} pre.format {font-family: inherit} pre.menu-comment {font-family: serif} pre.menu-preformatted {font-family: serif} span.nolinebreak {white-space: nowrap} span.roman {font-family: initial; font-weight: normal} span.sansserif {font-family: sans-serif; font-weight: normal} ul.no-bullet {list-style: none} --> </style> </head> <body lang="en"> <span id="Classes"></span><div class="header"> <p> Next: <a href="Advanced-Messaging.html" accesskey="n" rel="next">Advanced Messaging</a>, Previous: <a href="Objects.html" accesskey="p" rel="prev">Objects</a>, Up: <a href="index.html" accesskey="u" rel="up">Top</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Make.html" title="Index" rel="index">Index</a>]</p> </div> <hr> <span id="Writing-New-Classes"></span><h2 class="chapter">4 Writing New Classes</h2> <span id="index-writing-new-classes"></span> <p>Objective-C class definitions are always divided into two parts: an <i>interface</i> and an <i>implementation</i>. This division mirrors the common C library division into a header file with function declarations, which is distributed to all users of a library, and a source file with the implementations, which is only used to compile the library and is generally not distributed to users. A class interface declares instance variables, methods and the superclass name, while the implementation file holds the operational code that implements those methods. Typically the interface and implementation are held in separate files, using the <code>.h</code> and <code>.m</code> extensions, respectively. They may, however, be merged into one file, and a single file may implement many classes. </p> <span id="Interface"></span><h3 class="section">4.1 Interface</h3> <span id="index-interface"></span> <p>The interface is included in the source using <code>#include</code>: </p> <div class="example"> <pre class="example">#include "SomeClass.h" </pre></div> <p>To ensure that a Header file is included only once, it is usual to protect it with pre-compiler defines: </p> <div class="example"> <pre class="example">#ifndef _MY_CLASS_H_INCLUDED #define _MY_CLASS_H_INCLUDED /* HEADER FILE */ #endif </pre></div> <p>This is the standard C technique to protect header files from being included more than once. A cleaner alternative, introduced in Objective-C, is to use the <code>#import</code> directive instead of <code>#include</code>. The compiler will automatically include <code>#import</code>ed files no more than once, even if multiple <code>import</code> statements are encountered. Thus, you can do away with the messy preprocessor conditionals in the header file. </p> <p>You should be careful, however, to only use <code>#import</code> for Objective-C interface headers, and continue using <code>#include</code> for standard C files. It is possible, though not likely, that regular C headers may rely on being included multiple times in some cases. Also, you may need to include the compiler directive <code>-Wno-import</code> to gcc to avoid a didactic warning to this effect. </p> <span id="Interface-Capabilities"></span><h4 class="subsection">4.1.1 Interface Capabilities</h4> <p>The interface file declares new classes that can be used by source code, holding all the information necessary to use the classes from other Objective-C code. Firstly, the file reveals to the programmer the position of the class in the class hierarchy by defining exactly which is the superclass. Secondly, it informs programmers of what variables are inherited when they create subclasses. Finally, the interface file may inform other software entities of the messages that can be sent to the class object and to the instances of the class. </p> <p>Interface files use the <code>.h</code> extension as for ordinary C header files. (If you use emacs, put a line “<code>// -*-ObjC-*-</code>” at the top of your file to use the correct mode.) </p> <p>Here is an example of a class interface declaration: </p> <div class="example"> <pre class="example">#import <Foundation/NSObject.h> @interface Point : NSObject { @private // instance variables only accessible to instances of this class ... @protected // instance variables accessible to instances of this class or subclasses float x; float y; @public // instance variables accessible by all code ... } // class methods + (id) new; + (id) newWithX: (float)x0 Y: (float)y0; + (Point*) point; + (Point*) pointWithX: (float)x0 Y: (float)y0; // instance methods - (id) init; - (id) initWithX: (float)x0 Y: (float)y0; - (float) x; // (field accessor) - (float) y; - (void) setX: (float)newX; - (void) setY: (float)newY; @end </pre></div> <ul> <li> The interface file should import the interface of the superclass of the class it is defining. </li><li> The interface is enclosed between the compiler directives <code>@interface</code> and <code>@end</code>. </li><li> <code>@interface Point : Object</code> names the class and links it to the superclass. If no superclass is named, and the directive is without a colon, the compiler assumes that a root class is being created. You more than likely don’t want to do this. </li><li> Braces enclose declared instance variables; each class’s instance will have all these instance variables including instance variables inherited from the superclass, and from the superclass of the superclass, extending to the root class. </li><li> Instance variables may be declared as <code>private</code>, <code>protected</code>, or <code>public</code>. An instance’s <i>private</i> variables may only be accessed by instances of this class. An instance’s <i>protected</i> variables may be accessed by instances of this class or instances of subclasses of this class. <i>Public</i> variables may be accessed by any code. This is analogous to the usage in C++ and Java. If you do not mark your instance variable declaration explicitly, it is made <code>protected</code> by default. </li><li> Method declarations that begin with a "+" sign are class methods, and are defined for the class object. Thus, you can call them without creating an instance, and their implementations do not have access to any instance variables. A class object inherits class methods from superclasses. </li><li> Method declarations that begin with a "-" sign are instance methods, and are defined for class instances. Class instances inherit instance methods from superclasses. </li><li> A method may share the name of an instance variable. </li><li> A method return type is declared using the C syntax for type casts: <div class="example"> <pre class="example">- (float) x; </pre></div> <p>which is a method returning a float. </p> </li><li> Argument types can be declared in the same way as method return types: <div class="example"> <pre class="example">- (void) setX: (float)newX; </pre></div> <p>which is a method that returns nothing, and takes a single float as its argument. </p> <p>Note. The default type for methods and messages (<code>id</code>) is assumed when a return or argument type is not explicitly declared. For example, ’<code>-name</code>’ implicitly means a method returning <code>id</code> (i.e. an object). It is usually better to avoid this and use explicit typing as in </p><div class="example"> <pre class="example">- (NSString*) name; </pre></div> </li></ul> <span id="Including-Interfaces"></span><h4 class="subsection">4.1.2 Including Interfaces</h4> <p>Source code (including Objective-C implementation and interface files) may integrate interfaces using <code>#import</code> (or <code>#include</code>). Thereafter the source module may utilize the classes in those interfaces so as to: </p> <ul> <li> Make instances of them. </li><li> Send messages to invoke methods declared for them. </li><li> Refer to instance variables in them. </li></ul> <p>With the exception of the root class, all working interfaces integrate a superclass using either <code>#import</code> or <code>#include</code> – as was seen in the previous simplified interface file example. As a result the vast majority of class files begin with a standard form that includes their superclasses, and thus places them in the class hierarchy: </p> <div class="example"> <pre class="example">#import "SomeSuperclass.h" @interface SomeClass : SomeSuperclass { // instance variables ... } // method declarations ... @end </pre></div> <span id="Referring-to-Classes-_002d-_0040class"></span><h4 class="subsection">4.1.3 Referring to Classes - @class</h4> <p>It is possible for a source module to refer to classes without including their interface files. This is useful when you just need to tell the compiler that a certain word is a class name, but you want to avoid the overhead of including the whole interface file for that class. </p> <p>For example, to inform the compiler that <code>Border</code> and <code>Square</code> are classes without including their full interface file, the following syntax is used: </p> <p><code>@class Border, Square;</code> </p> <p>Class names may also appear in interface files at times when instance variables, return values and arguments are statically typed: </p> <div class="example"> <pre class="example">#import "Foundation/NSObject.h" @class Point @interface Square : NSObject { @protected Point *lowerLeft; float sideLength; } + (id) newWithLowerLeft: (Point *)lowerLeft sideLength: (float)sideLength; - (id) initWithLowerLeft: (Point *)lowerLeft sideLength: (float)sideLength; - (Point *) lowerLeft; - (float) sideLength; - (void) setLowerLeft: (Point *)newLowerLeft; - (void) setSideLength: (float)newSideLength; @end </pre></div> <p>Here, we see the <code>Point</code> class we declared earlier being used as a component in <code>Square</code>’s definition. Because this class is only referred to here to declare variables and method signatures, it suffices to reference it only using the <code>@class</code> directive. On the other hand, the implementation file may need to send messages to <code>Point</code> instances and would be better of importing the interface in this case. </p> <p>The compiler will produce a warning if you don’t include it, and no type checking can be performed (to see if class instances respond to the messages you send to them), but compilation will succeed. It is best to take advantage of type-checking when you can, however, and include interfaces that messages are to be sent to. </p> <p>There is one situation where you <i>must</i> include the interface however. If you are implementing a new class, you always need to include the interface of the superclass; <code>@class</code> cannot be used in this case because the compiler needs to know the details of the superclass and its instance variables etc., so as to create a fully working new class. If you try using <code>@class</code> in this situation, compilation will abort. </p> <span id="Implementation"></span><h3 class="section">4.2 Implementation</h3> <p>An interface file declares a class, while an implementation file implements it. The separation between the interface and implementation file yields a black box concept where the programmer using the class need only be concerned with the interface and its declared methods, superclasses, and instance variables. The implementation of classes is transparent to the programmer who may use them without detailed knowledge of their structures. </p> <p>Implementation files use the <code>.m</code> extension, to distinguish them from ordinary C files. </p> <span id="Writing-an-Implementation"></span><h4 class="subsection">4.2.1 Writing an Implementation</h4> <p>An implementation file contents are encapsulated between <code>@implementation</code> and <code>@end</code> directives: </p> <div class="example"> <pre class="example">#import "Point.h" @implementation Point // method implementations + (id)new { // statements ... } + (id)newWithX: (float)x Y: (float)y { // statements ... } // ... - (void)setY: (float)newY { // statements ... } @end </pre></div> <p>The implementation file uses <code>#import</code> to include a named interface file holding all declarations. Then it places method implementations for the class between <code>@implementation</code> and <code>@end</code> directives. Each method declared in the interface must be implemented. Instance variables may be referred to in instance methods (the ones with a “-” in front of them) but not class methods (the ones with a “+”). </p> <div class="example"> <pre class="example">- (float) x { return x; } - (void) setX: (float)newX { x = newX; } </pre></div> <span id="Super-and-Self"></span><h4 class="subsection">4.2.2 Super and Self</h4> <p>To assist in writing instance methods, Objective-C provides the two reserved words <b><code>self</code></b> and <b><code>super</code></b>. <code>Self</code> is used to refer to the current instance, and is useful for, among other things, invoking other methods on the instance: </p> <div class="example"> <pre class="example">- (Foo *) foo { if (![self fooIsInitialized]) [self initializeFoo]; return foo; } </pre></div> <p><code>Super</code> is used to refer to method implementations in the superclass of the instance. It is useful when overriding methods and when writing initializers, as discussed in the next section. </p> <span id="Instance-Initialization"></span><h4 class="subsection">4.2.3 Instance Initialization</h4> <p>Instance initialization is one of the trickier aspects of getting started in Objective-C. Recall that instances of a class are created by use of the class <code>alloc</code> method (inherited from <code>NSObject</code>) but are initialized by instance methods. This works a little differently than in C++ and Java, where constructors are special methods that are neither class nor instance methods. In particular, since initializer methods are inherited instance methods, they may still be called even if you have not implemented them in your class. For example, it is always valid to invoke </p> <div class="example"> <pre class="example">SomeComplexClass *c = [[SomeComplexClass alloc] init]; </pre></div> <p>Even if you have not implemented <code>init</code> in <code>SomeComplexClass</code>, the superclass’s implementation will be invoked, or, ultimately, <code>NSObject</code>’s if no other ancestors implement it. Obviously, this could result in some of <code>SomeComplexClass</code>’s internal state being left uninitialized. For this reason, you should always either provide an <code>init</code> implementation, or document whether it should be used. We will return to this concern below. </p> <p>Typically, a class will also provide one or more <code>initWith...</code> methods for initialization with arguments, and it may optionally also provide <code>+new</code> methods and convenience class methods that act like constructors. The general approach to implementing these is illustrated here for the <code>Point</code> class. </p> <div class="example"> <pre class="example">+ new { Point *point; // note "self" refers to the "Point" _class_ object! point = [[self allocWithZone: NSDefaultMallocZone()] init]; return point; } + newWithX: (float)x0 Y: (float)y0 { Point *point; point = [[self allocWithZone: NSDefaultMallocZone()] initWithX: x Y: y]; return point; } + point { Point *point; // note "self" refers to the "Point" _class_ object! point = [self new]; return AUTORELEASE(point); } + pointWithX: (float)x0 Y: (float)y0 { Point *point; point = [self newWithX: x Y: y]; return AUTORELEASE(point); } - init { return [self initWithX: 0.0 Y: 0.0]; } // this is the "designated" initializer - initWithX: (float)x0 Y: (float)y0 { self = [super init]; if (self != nil) { x = x0; y = y0; } return self; } </pre></div> <p>Notice that, first, the convenience constructors (<code>new</code> and <code>newWithX:Y:</code>) execute <code>[self allocWithZone:]</code> to begin with. The “<code>self</code>” here refers to the <i>class</i> object, since it is used inside a <i>class</i> method. Thus the effect is the same as if “<code>[Point alloc]</code>” had been executed in external code. Second, notice that the other convenience constructors (<code>point</code> and <code>pointWithX:Y:</code>) autorelease the new instance before returning it. This is to follow the rules of memory management discussed in <a href="Objects.html">Memory Management</a>. Third, note that the <code>new..</code> methods each call a corresponding <code>init...</code> method. It is not necessary to maintain such a one to one correspondence but it is a common convention to have the convenience implementations rely on instance <code>init</code> methods as shown. Fourth, note that the use of <code>[self allocWithZone: NSDefaultMallocZone()]</code> rather than <code>[self alloc]</code> is generally unnecessary, but provides a slight efficiency gain since <code>+alloc</code> is implemented by calling <code>+allocWithZone:</code> on the default zone. </p> <p><b>Designated Initializer</b> </p> <p>Finally, notice that the <code>initWithX:Y:</code> method is marked as the “designated” initializer. This concept is important to ensure proper initialization for classes within a hierarchy. The designated initializer should be the one with the most control over the nature of the new instance, and should be the one that all other initializers “ground out” in. In other words, all other initializers should be chained so that they either call the designated initializer, or they call another initializer that (eventually) calls it. </p> <p>The importance of having a designated initializer is this: when a subclass is created, it need only override the designated initializer to ensure that all of its instances are properly initialized. If this is not done, external code could invoke an initializer that initializes only the superclass’s instance variables, and not the subclass’s. To avoid this, each class designates a “ground out” initializer to which other initializers ultimately delegate. Then the subclass overrides this initializer, and in its own designated initializer, makes a call to it, to ensure that the superclass is initialized properly. Thus: </p> <div class="example"> <pre class="example">@implementation SuperClass - initWithA: (int)a { return [self initWithA:a B:0]; // 0 is default value } // designated init for SuperClass - initWithA: (int)a B: (int)b { self = [super init]; myA = a; myB = b; return self; } @end @implementation SubClass // overrides SuperClass's designated init - initWithA: (int)a B: (int)b { return [self initWithA: (int)a B: (int)b C: (int)c]; } // designated init for SubClass - initWithA: (int)a B: (int)b C: (int)c { self = [super initWithA: a B: b]; myC = c; return self; } @end </pre></div> <p>Note, as shown above, unlike in some other object-oriented languages, ’<code>self</code>’ is a variable that can be redefined. For example, we could have written the <code>new</code> constructor above like this: </p> <div class="example"> <pre class="example">{ self = [[self alloc] init]; // note "self" now refers to the new instance! [self setX: 1.0]; return self; } </pre></div> <p>Another point to note is that Objective-C does not enforce calling superclass initializers before carrying out subclass initialization. Although above the first call in the designated initializer was always <code>[super ...]</code>, this was not required, and if you need to set something up before <code>super</code> acts, you are free to do so. </p> <span id="Flexible-Initialization"></span><h4 class="subsection">4.2.4 Flexible Initialization</h4> <p>As mentioned before, it is possible for an initialization process to, if desired, return not a new object but an existing object. This may be done in one of two ways. If you are doing it from a convenience class method like <code>new</code>, then use something like the following: </p> <div class="example"> <pre class="example">+ new { if (singleton == nil) singleton = [[self alloc] init]; return singleton; } </pre></div> <p>Note this example presupposes the existence of a class variable, ’<code>singleton</code>’. Class variables as such don’t exist in Objective-C but can be simulated, as discussed below. </p> <p>If you want to possibly return an existing instance from an init instance method like <code>init</code>, the procedure is slightly more complicated: </p> <div class="example"> <pre class="example">- init { if (singleton != nil) { RELEASE(self); self = RETAIN(singleton); } else { singleton = self; } return self; } </pre></div> <p>Here, we explicitly <b>deallocate</b> the current instance and replace it with the desired existing instance. Because this might happen, you should always be careful to use the returned value from an <code>init</code> method: </p> <div class="example"> <pre class="example">id anObject = [SomeClass alloc]; // this is bad: [anObject init]; // anObject might have been deallocated! // do this instead: anObject = [anObject init]; </pre></div> <p>One scenario where this actually occurs in the GNUstep libraries is with the class <code>NSConnection</code>. It only permits one connection to exist between any two ports, so if you call <code>initWithReceivePort:sendPort:</code> when a connection for the ports exists, the method will deallocate the newly allocated instance, and return the current conflicting object, rather than the receiver. </p> <p>In general, it is better to catch this type of requirement in a “<code>new</code>” class method rather than an instance “<code>init</code>” method so as to avoid the unnecessary allocation of instances that will not be used, however this is not always possible given other design constraints. </p> <span id="Instance-Deallocation"></span><h4 class="subsection">4.2.5 Instance Deallocation</h4> <p>As described in <a href="Objects.html">Memory Management</a>, objects should be deallocated when they are no longer needed. When garbage collection is not being used, this is done through explicit calls to the <code>dealloc</code> method. When GC <i>is</i> being used, <code>dealloc</code> is still called implicitly, and should be implemented. However the tasks of the <code>dealloc</code> method are fewer in this case. </p> <p>When garbage collection is <i>not</i> active, the <code>dealloc</code> method must release all other objects that this instance has retained. Usually these are those instance variables that are objects rather than primitive types. In certain cases such as container classes, other objects must be released as well. In addition, if the instance has acquired any external resources, such as a network connection or open file descriptor, these should be relinquished as well. Likewise, any memory that has been directly allocated through use of <code>malloc</code> or other functions should be released. </p> <p>When garbage collection <i>is</i> active, the <code>dealloc</code> method is still responsible to relinquish external resources, but other GNUstep objects need not be released, since they will be garbage collected once this instance has been. </p> <p>If you cannot be sure whether your class will be running in a garbage-collecting environment, it never hurts to execute all of the releases of other objects. This will not harm the operation of the garbage collector, though it will result in pointless calls to the retain/release methods that are stubbed out under garbage collection. If this could cause a performance hit in your application, you should use the RETAIN/RELEASE macros instead of the function calls. </p> <p>Here is an example of a <code>dealloc</code> implementation: </p> <div class="example"> <pre class="example">- dealloc { RELEASE(anInstanceVariableObject); NSZoneFree(NULL, myMemory); [super dealloc]; } </pre></div> <p>Here, we use the <code>RELEASE</code> macro to release an instance variable, and the <code>NSZoneFree</code> function to free memory that was earlier allocated with <code>NSZoneMalloc</code> or a related function. (See <a href="Base-Library.html">Base Library</a> for discussion of GNUstep’s raw memory allocation functions.) The <code>NULL</code> used indicates that the memory was from the default zone, and is equivalent to saying ’<code>NSDefaultMallocZone()</code>’ instead. </p> <p>Finally, notice we end with a call to <code>[super dealloc]</code>. This should always be done in <code>dealloc</code> implementations, and you should never concern yourself with deallocating structures that are associated with a superclass, since it will take care of this itself. </p> <span id="Protocols"></span><h3 class="section">4.3 Protocols</h3> <span id="index-protocols"></span> <span id="index-protocols_002c-formal"></span> <p>Protocols in Objective-C provide a level of flexibility beyond class structure in determining what messages objects respond to. They are similar to interfaces in Java but more flexible. </p> <p>There are two types of protocol in Objective-C: <b>informal</b> protocols, where we document methods to which objects will respond, and specify how they should behave, and <b>formal</b> protocols, where we provide a list of methods that an object will support in a format where the compiler can check things, and the runtime can also check that an object conforms to the protocol. Informal protocols are merely convention, but are useful where we want to say that some system will work as long as it (or its delegate) implements some subset of a group of methods. Formal protocols are of more use when we want the compiler or runtime to check that an object implements all of a group of methods itself. Formal protocols form an inheritance hierarchy like classes, and a given class may conform to more than one protocol. Thus, formal protocols are identical in many respects to Java <i>interfaces</i>. </p> <p>As in Java, a particularly important use of protocols is in defining the methods that an object in a remote process can respond to … by setting the protocol used by a local proxy object, you can avoid having to send messages to the remote process to check what methods are available - you can simply check the local protocol object. This will be covered later in <a href="Distributed-Objects.html">Distributed Objects</a>. </p> <p>Informal protocols are closely associated with <i>Categories</i>, another Objective-C language facility, and will be discussed in the next section. </p> <span id="Declaring-a-Formal-Protocol"></span><h4 class="subsection">4.3.1 Declaring a Formal Protocol</h4> <p>A formal protocol is declared as a series of method declarations, just like a class interface. The difference is that a protocol declaration begins with <code>@protocol</code> rather than <code>@interface</code>, and has an optional <b>super</b> protocol specified in angle brackets. </p> <div class="example"> <pre class="example">@protocol List - (void) add: (id) item; - (void) remove: (id) item; - getAtIndex: (int)idx; - (void) clear; @end @protocol LinkedList <List> - (void) addFirst: (id)item; - (void) addLast: (id)item; - getFirst; - getLast; @end </pre></div> <span id="Implementing-a-Formal-Protocol"></span><h4 class="subsection">4.3.2 Implementing a Formal Protocol</h4> <p>If you want your class to conform to a protocol, you declare it in your interface, and implement the methods in your declaration: </p> <div class="example"> <pre class="example">@interface BiQueue <LinkedList> { // instance variables ... } // method declarations ... // [don't need to redeclare those for the LinkedList protocol] - takeFirst - takeLast @end ... @implementation BiQueue // must implement both List's and LinkedList's methods ... - add: (id) item { // ... } - addFirst: (id)item { // ... } @end </pre></div> <p>To declare conformance to multiple protocols, do something like this: </p> <div class="example"> <pre class="example">@interface ContainerWindow < List, Window > ... @end </pre></div> <p>The implementation must include all methods in both protocols. </p> <span id="Using-a-Formal-Protocol"></span><h4 class="subsection">4.3.3 Using a Formal Protocol</h4> <p>To use a formal protocol, simply send objects the messages in the protocol. If you want type-checking, you must either use the type of a class implementing the protocol, or use a special syntax: </p> <div class="example"> <pre class="example">... BiQueue queue = [[BiQueue alloc] init]; // send a LinkedList message [queue addFirst: anObject]; // alternatively, we may stipulate only that an object conforms to the // protocol in the following way: id<LinkedList> todoList = [system getTodoList]; task = [todoList getFirst]; ... </pre></div> <p>In the last part of this example, we declare that <code>todoList</code> is an object that conforms to the <code>LinkedList</code> protocol, but do not specify what class it may be an instance of. </p> <p>If you are not sure the returned object does indeed conform to the protocol you are interested in, you can check it: </p> <div class="example"> <pre class="example">if ([anObject conformsToProtocol: aProtocol] == YES) { // We can go ahead and use the object. } else { NSLog(@"Object of class %@ ignored ... does not conform to protocol", NSStringFromClass([anObject class])); } </pre></div> <p>Finally, you can specify an object conforming to <i>multiple</i> protocols in the same way you declare it in an interface: </p> <div class="example"> <pre class="example">id <LinkedList, Window> windowContainerOfUnknownClass; </pre></div> <span id="Categories"></span><h3 class="section">4.4 Categories</h3> <span id="index-categories"></span> <p>Categories provide a way in Objective-C to add new methods to an existing class, without declaring a subclass. Once the category is declared and implemented, all instances of the existing class that are created will include the capability to respond to the new methods. Furthermore, subclasses of the class will inherit these methods. However, it is not possible to add instance variables to a class using a category. Categories do not have an obvious parallel in other major object-oriented languages (with the exception of Ruby), but it is well worth taking the trouble to understand them and the benefits they can provide. </p> <p>A category is declared in connection with the class it is going to modify. (You can think of it as a new “category” of instances of this class.) </p> <div class="example"> <pre class="example">#import "Point.h" @interface Point (Transformable) - translateByX: (float)tx Y: (float)ty; - rotateByAngle: (float)radians; - scaleByAmountX: (float)xscale Y: (float)yscale; @end </pre></div> <p>You then provide an implementation file more or less analogously to that for a class, where you implement just the new methods: </p> <div class="example"> <pre class="example">#import "PointTransformable.h" @implementation Point (Transformable) - (void) translateByX: (float)tx Y: (float)ty { x += tx; y += ty; return self; } - (void) rotateByAngle: (float)radians { // ... } - (void) scaleByAmountX: (float)xscale Y: (float)yscale { // ... } @end </pre></div> <p>Notice that you have access to instance variables of the class you are creating a category of; this includes private and protected variables. </p> <p>One of the primary uses of categories is illustrated by this example. Suppose you are working with a third party drawing package that uses some geometrical classes such as <code>Point</code> and <code>Line</code>. You are developing an animation program based on the package and need the ability to move things around. Rather than employing a complex subclassing or aggregation scheme to add these capabilities, you simply define the <code>Transformable</code> category for each of the geometrical entities. At runtime, all instances of these entities, whether created by you or the package itself, have the additional methods. The presence of these methods does not affect the existing operation of this or any third party package, but allows you to conveniently implement the enhanced functionality you need. </p> <span id="Category-Overrides"></span><h4 class="subsection">4.4.1 Category Overrides</h4> <p>You can also use categories to override methods that a class already has. If you do so, you cannot access an existing implementation in the class itself, however you can still call <code>[super someMethod]</code> to access an implementation inherited from a superclass. You obviously need to be careful not to break existing functionality. </p> <p>You can add multiple categories to a class by declaring them and implementing them separately. Instances of the class will then implement <i>all</i> of the categories declared. The order in which the category implementations are searched for methods is not defined, therefore you cannot override a method implemented in one category with an implementation in another. </p> <span id="Categories-as-an-Implementation-Tool"></span><h4 class="subsection">4.4.2 Categories as an Implementation Tool</h4> <p>Categories are not just useful for extending an existing class. Another major use for categories is to separate the implementation of a <i>new</i> class into a number of source files. (Each file implements one category of the new class, and at runtime instances of the class respond to the methods in all the categories.) The benefits of this program development strategy include: grouping subject-oriented methods; incremental compilation for large classes; helping to logically divide the class when being created by a number of developers; and, permitting configuration-specific classes targeting particular applications. </p> <span id="Categories-and-Protocols"></span><h4 class="subsection">4.4.3 Categories and Protocols</h4> <p>As described in the previous section, in addition to the <i>formal</i> protocol facility described, Objective-C provides for <i>informal</i> protocols. An informal protocol is essentially a category declaration without an implementation. Usually, the informal protocol is declared as a category for a high-level object, such as <code>NSObject</code>, then each class that actually wishes to implement something in the protocol lists the methods it chooses to implement in its interface and provides implementations in its implementation. </p> <span id="Simulating-Private-and-Protected-Methods"></span><h3 class="section">4.5 Simulating Private and Protected Methods</h3> <p>Unlike most object-oriented languages Objective-C does not provide for method scoping. Instead, all methods are effectively public. Often, however, it is useful to have internal “utility” methods that help a class do its job but are hidden from external use. Rather than cluttering up the class’s API with a bunch of methods marked “do not use”, one wants to make these methods visible only to subclasses, or only to the class itself. Categories can help in this regard. </p> <p><b>Using Categories</b> </p> <p>One common approach is to define a category within a class’s <i>implementation</i> file: </p> <div class="example"> <pre class="example"> #import "Point.h" @interface Point (Private) -(BOOL) isPositiveQuadrant; @end @implementation Point // public method implementations ... @end @implementation Point (Private) -(BOOL) isPositiveQuadrant { return (x > 0) && (y > 0) ? YES : NO; } @end </pre></div> <p>All of this code would appear in the file <code>Point.m</code>. What this does is add a category to Point defining the private methods. Since external code only “knows about” <code>Point</code> through its interface file, these additional methods are effectively invisible. However, you should be aware that external code is not prevented from actually calling the private methods, if it happens to know about them. However the compiler will produce a warning if you try to do this with a typed variable: </p> <div class="example"> <pre class="example">Point *p = [[Point alloc] init]; // works, but produces a compile warning BOOL b = [p isPositiveQuadrant]; </pre></div> <p>The bright side of this is it allows you to simulate <i>protected</i> methods as well. For this, the writer of a subclass must be informed in some way about the protected methods, and they will need to put up with the compiler warnings. Alternatively, you could declare the Protected category in a separate interface file (e.g., “<code>PointProtected.h</code>”), and provide this interface file with the understanding that it should only be imported and used by a subclass’s interface file. </p> <p><b>Using Convention</b> </p> <p>Another approach to providing <i>protected</i> methods that the class or subclass can use is to prefix these methods with an underscore (’_’). These methods will still be visible publicly, but programmers will know, by convention, not to use them externally, and the <a href="GSDoc.html">GNUstep documentation system</a> will automatically mark these in API documentation as off-limits. </p> <p>An alternative approach to providing <i>private</i> methods is to simply declare them as functions within the implementation file itself. The catch to this is that these functions will <i>not</i> have access to the class’s instance variables. You will need to pass these in manually whenever you invoke them from an ordinary method. </p> <span id="Simulating-Class-Variables"></span><h3 class="section">4.6 Simulating Class Variables</h3> <p>While Objective-C does not provide for variables that are associated with the class as a whole rather than an instance, these are often useful. It is possible to simulate them to a limited extent by declaring static variables in the implementation file for the class (inside the <code>@implementation</code> block). The variables will not be available to subclasses, unless they explicitly declare them “<code>extern</code>” and are compiled at the same time. </p> <p>... </p> <hr> <div class="header"> <p> Next: <a href="Advanced-Messaging.html" accesskey="n" rel="next">Advanced Messaging</a>, Previous: <a href="Objects.html" accesskey="p" rel="prev">Objects</a>, Up: <a href="index.html" accesskey="u" rel="up">Top</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Make.html" title="Index" rel="index">Index</a>]</p> </div> </body> </html>