Added objective-c programming manual.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12373 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-02-01 16:13:20 +00:00
parent af55de2283
commit 20e890b039
17 changed files with 4282 additions and 0 deletions

View file

@ -1,3 +1,11 @@
2002-02-01 Richard Frith-Macdonald <rfm@gnu.org>
* Documentation/manual: New directory containing Objective-C and
GNUstep-base programming manual/tutorial produced at Brainstorm.
The intention was to produce a pretty complete manual and then
release it, but we ran out of funding, so I'm releasing the work
to date.
2002-02-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Makefile.preamble: remove old GSI api support

View file

@ -0,0 +1,130 @@
@paragraphindent 0
@node Advanced Topics
@chapter Advanced Topics
@cindex advanced topics
@section Forwarding
@cindex forwarding
When an object is unable to respond to a message, the Objective-C
runtime sends a @code{forwardInvocation:} message to the object, and
the object is then able to use the information provided to handle the
message in some way, a common mechanism being to forward the message
to another object known as a @b{delegate}, so that the other object
can deal with it.
@example
- (void) forwardInvocation: (NSInvocation*)objectInvoke
@{
if ([forwardObject respondsToSelector: [objectInvoke selector]])
return [objectInvoke invokeWithTarget: forwardObject];
else
return [self doesNotRecognizeSelector: [objectInvoke selector]];
@}
@end example
@itemize @bullet
@item
@code{objectInvoke} is another object (of the @code{NSInvocation} class)
which has all the information about the original message sent, including
its @b{selector} and its arguments.
@item
@code{self} refers to the object or receiver.
@end itemize
@b{Note. this is a powerful method for creating software patterns for
multiple inheritance, journaling, and dispatching messages to
dynamically loaded code.}
@subsection Forwarding and Multiple Inheritance
Forwarding is a form of multiple inheritance. The diagram below shows a simple scenario where an instance of the @code{Chat} class passes the @b{negotiate} message to an instance of the @code{ChatTwo} class. The forwarding object therefore inherits methods from its own inheritance path and from that of the receiving object.
@subsection Surrogate Objects
Surrogate objects forward messages to objects that can be assumed to be more complex. The @code{forwardInvocation:} method of the surrogate object receives a message that is to be forwarded; it determines whether or not the receiver exists, and if it does not, then it will attempt to create it. A @b{proxy object} is a common example of a surrogate object. A proxy object performs obvious functions that we have already discussed:
@itemize @bullet
@item
provides a local address for a remote object
@item
queues messages
@item
forwards messages to typically remote receivers
@item
copies and retrieves arguments over the connection.
@end itemize
@subsection Forwarding vs Inheritance
The main difference between @b{Forwarding} and @b{Inheritance} surfaces in the application of methods like @code{respondsToSelector} and @code{isKindOfClass:}. This is because these methods search the inheritance path, but ignore the forwarding path.
(See Section 1.6.6 @code{respondsToSelector.})
@b{Note. @code{respondsToSelector} does not trace the forwarding chain, and can therefore erroneously report that an object does not respond to a particular message, when it does.}
@comment Making Forwarding Transparent
@section Exception Handling
@section Copying, Comparing, Hashing Objects
@itemize @bullet
@item
deep copy vs swallow copy
@item
simple copy vs mutable copy
@item
isEqual:, hash
@end itemize
@section Dictionaries, Arrays, Containers
@section Coding
@itemize @bullet
@item
Possibilities offered by Coding
@item
Type Encoding
@end itemize
@section Property Lists
@itemize @bullet
@item
What are property lists
@end itemize
@section Bundles
@section UserDefaults
@section Threading
General discussion about threading with gnustep base, what is
thread-safe, what is not, how to start new threads, NSThread briefly
introduced with examples.
[Nicola: important: talk about NSConnection enableMultipleThreads]].

View file

@ -0,0 +1,935 @@
@paragraphindent 0
@node Distributed Objects
@chapter Distributed Objects
@cindex distributed objects
Until now we have been concentrating on using the Objective-C language
to create programs that execute in a single process. But what if you
want your program to interact with objects in other processes, perhaps
running on different machines?
As a simple example, we may have a client process that needs to access a
telephone directory stored on a remote server. The client process could
send a message to the server that contained a person's name, and the
server could respond by returning that person's number.
The GNUstep base library provides a powerful set of classes that make
this type of remote messaging not only possible, but easy to program. So
what do these classes do and how can we use them? To answer that we must
first look at the way code interacts with objects in a single process,
and then look at how we can achieve the same interaction with objects
that exist in different processes.
@section Object Interaction
@cindex object interaction, remote objects
To continue with the example above, if the telephone directory existed
in the same process as the code that was accessing it, then a simple
message would return the wanted telephone number.
@example
NSString *wantedNumber = [telephoneDirectory teleNumber: personName];
@end example
Now object and method names just hold pointers to memory addresses. The
code executed at run time in response to the @code{teleNumber} message
is located at an address held by the name of the responding method (a
variable), while data in the telephone directory is located at an
address held by the @code{telephoneDirectory} variable.
In a single process these addresses can be accessed by the client code
at run time, but if the telephone directory is located on a remote
server, then the address of the remote object is not known in the client
process (the @code{telephoneDirectory} object and its responding method
are said to exist in a separate 'address space').
The Objective-C run-time library was not designed for this inter-process
communication or 'remote messaging'.
@section The GNUstep Solution
@cindex distributed objects
@cindex remote objects
@cindex client/server processes
@cindex NSConnection class
@cindex NSProxy class
@cindex NSRunLoop class
GNUstep overcomes these limitations by providing you with classes that
form, what is known as, a 'distributed objects' architecture that
extends the capabilities of the run-time system.
With the addition of a few lines of code in the client and server
programs, these extensions allow you to send a message to a remote
process by constructing a simple Objective-C statement. In the telephone
directory example, the statement to retrieve the telephone number would
now look something like this:
@example
NSString *wantedNumber = [proxyForDirectory teleNumber: personName];
@end example
Compare this to the original statement:
@example
NSString *wantedNumber = [telephoneDirectory teleNumber: personName];
@end example
Notice that the only difference between the two statements is the name
of the object receiving the message, i.e. @code{proxyForDirectory}
rather than @code{telephoneDirectory}. GNUstep makes it as simple as
this to communicate with an object in another process.
The variable @code{proxyForDirectory} is known as a 'proxy' for the
remote @code{telephoneDirectory} object. A proxy is simply a substitute
for the remote object, with an address in the 'address space' of the
local client process, that receives messages and forwards them on to the
remote server process in a suitably coded form.
Let us now take a look at the additional lines of code required to make
this 'remote messaging' possible.
@subsection Code at the Server
@cindex server code, GNUstep
@cindex GNUstep server code
In order to respond to client messages, the responding server object
must be set as the 'root object' of an instance of the NSConnection
class, and this NSConnection must be registered with the network by
name. Making an object available to client processes in this way is
known as 'vending' the object. The registered name for the NSConnection
is used by the client when obtaining a proxy for the responding server
object over the network.
The only other code you need to consider is the code that listens for
incoming messages. This 'runloop' as it is known, is started by sending
a @code{run} message to an instance of the NSRunLoop class. Since an
NSRunLoop object is created automatically for each process, there is no
need to create one yourself. Simply get the default runloop, which is
returned by the @code{currentRunLoop} class method.
When the runloop detects an incoming message, the message is passed to
the root object of the NSConnection, which performs a method in response
to the message and returns a variable of the appropriate type. The
NSConnection manages all inter-process communication, decoding incoming
messages and encoding any returned values.
The code to vend the @code{telephoneDirectory} object and start the
runloop would look something like this:
@example
/*
* Remember, create an instance of the
* NSAutoreleasePool class.
*/
CREATE_AUTORELEASE_POOL(pool);
/*
* Get the default NSConnection object
* (a new one is automatically created if none exists).
*/
NSConnection *connXion = [NSConnection defaultConnection];
/*
* Set the responding server object as
* the root object for this connection.
*/
[connXion setRootObject: telephoneDirectory];
/*
* Try to register a name for the NSConnection,
* and report an error if this is not possible.
*/
if ([connXion registerName: @@"DirectoryServer"] == NO)
@{
NSLog(@@"Unable to register as 'DirectoryServer'");
NSLog(@@"Perhaps another copy of this program is running?");
exit(1);
@}
/* Start the current runloop. */
[[NSRunLoop currentRunLoop] run];
/* Release the pool */
RELEASE(pool);
@end example
These additional lines of code turn a program into a distributed objects
server, ready to respond to incoming client messages.
@subsection Code at the Client
@cindex client code, GNUstep
@cindex GNUstep client code
At the client, all you need do is obtain a proxy for the responding
server object, using the name that was registered for the NSConnection
at the server.
@example
/* Create an instance of the NSAutoreleasePool class */
CREATE_AUTORELEASE_POOL(pool);
/* Get the proxy */
id proxy = [NSConnection
rootProxyForConnectionWithRegisteredName:
@i{registeredServerName}
host: @i{hostName}];
/* The rest of your program code goes here */
/* Release the pool */
RELEASE(pool);
@end example
The code that obtains the proxy automatically creates an NSConnection
object for managing the inter-process communication, so there is no need
to create one yourself. If the @i{hostName} in this statement is 'nil',
then only the local host will be searched to find the
@i{registeredServerName}. If @i{hostName} is "*", then all hosts on the
network will be searched.
In the telephone directory example, the code to obtain the proxy from
any host on the network would be:
@example
id proxyForDirectory = [NSConnection
rootProxyForConnectionWithRegisteredName:
@@"DirectoryServer"
host: "*"];
@end example
With this additional line of code in the client program, you can now
construct a simple Objective-C statement to communicate with the remote
object.
@example
NSString *wantedNumber = [proxyForDirectory teleNumber: personName];
@end example
@subsection Using a Protocol
@cindex protocol for distributed objects
@cindex distributed objects, using a protocol
A client process does not need to know the class of a remote server
object to avoid run-time errors, it only needs to know the messages to
which the remote object responds. This can be determined by the client
at run-time, by asking the server if it responds to a particular message
before the message is sent.
If the methods implemented at the server are stated in a formal
protocol, then the client can ask the server if it conforms to the
protocol, reducing the network traffic required for the individual
message/response requests.
A further advantage is gained at compile time, when the compiler will
issue a warning if the server fails to implement any method declared in
the protocol, or if the client contains any message to which the server
cannot respond.
The protocol is saved to a header file and then included in both client
and server programs with the usual compiler @code{#include}
directive. Only the server program needs to implement the methods
declared in the protocol. To enable compiler checking in the client
program, extend the type declaration for the proxy to this protocol, and
cast the returned proxy object to the same extended type.
In the telephone directory example, if the declared protocol was
@code{TelephoneDirectory}, declared in header file
@code{protocolHeader.h}, then the client code would now look like this:
@example
#include "protocolHeader.h";
/* Extend the type declaration */
id<TelephoneDirectory> proxyForDirectory;
/* Cast the returned proxy object to the extended type */
proxyForDirectory = (id<TelephoneDirectory>) [NSConnection
rootProxyForConnectionWithRegisteredName:
@@"DirectoryServer"
host: "*"];
@end example
Since class names and protocol names do not share the same 'address
space' in a process, the declared protocol and the class of the
responding server object can share the same name, making code easier to
understand.
For example, @code{proxyForDirectory} at the client could be a proxy for
an instance of the @code{TelephoneDirectory} class at the server, and
this class could implement the @code{TelephoneDirectory} protocol.
@section An Example Game Server
@cindex distributed objects, example (no error checking)
It would be tempting to show a complete example of the telephone
directory program, but a minimal amount of additional code is required
to turn the previous examples into a working implementation. Instead we
will look at an example called GameServer that uses distributed objects
in a client/server game.
@i{Exercise: Create a working client/server telephone directory on your
own by adding a few lines of code to the previous examples, perhaps with
a telephone directory holding only two or three names and numbers. At
first you could implement this as a single process and then when it
works, modify the code to run as client/server processes running on the
same machine. (Try passing the person's name into the client program as
a command-line argument. The server need only test the name, e.g. if
personName = "Fred" return "number".)}
@i{All you need do is create two directories, one for the client and one
for the server. Each directory will hold a GNUmakefile, the
client/server source code, and a copy of the protocol header file. When
the files compile, first run the server and then the client. What
happens when you run the client without the server? How would you
display a "No Server Connection" warning at the client? Appendix B
contains a small working example that you can compare with your own
implementation.}
@subsection What GameServer Does
@cindex game server example
Although there is no actual game to play, and while the code to vend an
object and connect to a remote process is similar to that already shown,
the code does show a number of additional techniques that can be used in
other client/server programs.
@itemize @bullet
@item When the client attempts to join the game, the server checks that
the client is entitled to join, based on the last time the client
played.
The rule is: if the client lost the last game, then they cannot re-play
for the next 2 hours; but if the client won the last game, then they can
re-play the game at any time (a reward for winning).@*@*
@item The server also makes sure the client is not already connected and
playing the game (i.e. they cannot play two games at the same time -
that would be cheating).@*@*
@item In addition to a proxy for the server being obtained at the
client, a proxy for the client is received at the server. This allows
two-way messaging, where the client can send messages to the server and
the server can send messages to the client (e.g. the state of play may
be affected by the actions of other players, or by other events at the
server).@*@*
Two protocols will therefore be required, one for the methods
implemented at the server and one for those implemented at the client.
@end itemize
Have a look at the program code and added comments. Can you work out
what is happening at the server and client? If you have any difficulties
then refer to the relevant sections in this manual, or to class
documentation at the GNUstep or Apple web-sites.
@subsection Protocol Adopted at Client
We have chosen @code{GameClient} as the name of both the protocol
adopted at the client and the class of the responding client object. The
header file declaring this protocol will simply declare the methods that
the class must implement.
@example
@@protocol GameClient
- (void) clientMessage: (bycopy NSString *)theMessage;
- (int) clientReply;
// Other methods would be added that
// reflect the nature of the game.
@@end
@end example
The protocol will be saved as @code{GameClient.h}.
@subsection Protocol Adopted at Server
We have chosen @code{GameServer} as the name of both the protocol
adopted at the server and the class of the responding server object. The
header file declaring this protocol will simply declare the methods that
the class must implement.
@example
@@protocol GameServer
- (BOOL) mayJoin: (id)client asPlayer: (bycopy NSString*)name;
- (int) startGame: (bycopy NSString*)name;
- (BOOL) endGame: (bycopy NSString*)name;
// Other methods would be added that
// reflect the nature of the game.
@@end
@end example
The protocol will be saved as @code{GameServer.h}.
@subsection Code at the Client
The client code contains the @code{main} function and the
@code{GameClient} class declaration and implementation.
The @code{main()} function attempts to connect to the server, while the
@code{GameClient} class adopts the @code{GameClient} protocol.
@example
#include <Foundation/Foundation.h>
#include "GameServer.h"
#include "GameClient.h"
/*
* GameClient class declaration:
* Adopt the GameClient protocol.
*/
@@interface GameClient : NSObject <GameClient>
@@end
/*
* GameClient class implementation.
*/
@@implementation GameClient
/*
* Implement clientMessage: as declared in the protocol.
* The method simply prints a message at the client.
*/
- (void) clientMessage: (NSString*)theMessage
@{
printf([theMessage cString]);
@}
/*
* Implement clientReply: as declared in the protocol.
* The method simply returns the character entered
* at the client keyboard.
*/
- (int) clientReply
@{
return getchar();
@}
@@end // End of GameClient class implementation.
/*
* The main function of the client program.
*/
int main(int argc, char **argv)
@{
CREATE_AUTORELEASE_POOL(pool);
id<GameServer> server;
int result;
NSString *name;
id client;
/*
* The NSUserName() function returns the name of the
* current user, which is sent to the server when we
* try to join the game.
*/
name = NSUserName();
/*
* Create a GameClient object that is sent to
* the server when we try to join the game.
*/
client = AUTORELEASE([GameClient new]);
/*
* Try to get a proxy for the root object of a server
* registered under the name 'JoinGame'. Since the host
* is '*', we can connect to any server on the local network.
*/
server = (id<GameServer>)[NSConnection
rootProxyForConnectionWithRegisteredName:
@@"JoinGame" host: @@"*"];
if(server == nil)
@{
printf("\n** No Connection to GameServer **\n");
result = 1;
@}
/*
* Try to join the game, passing a GameClient object as
* the client, and our user-name as name. The 'client'
* argument will be received as a proxy at the server.
*/
else if ([server mayJoin: client asPlayer: name] == NO)
@{
result = 1; // We cannot join the game.
@}
else
@{
/*
* At this point, we would actually start to play the game.
*/
[server startGame: name]; // Start playing game.
[server endGame: name]; // Finally end the game.
result = 0;
@}
RELEASE(pool);
return result;
@}
@end example
To summarise the code at the client:
@itemize @bullet
@item We obtained a proxy for the server and can now communicate
with the server using the methods declared in the @code{GameServer}
protocol.@*@*
@item We passed a @code{GameClient} object and our user-name to the
server (the @code{GameClient} object is received as a proxy at the
server). The server can now communicate with the client using the
methods declared in the @code{GameClient} protocol.@*@*
@item When the game is in progress, the server can alter the state
of the client object to reflect the success of the player.
@end itemize
@subsection Code at the Server
The server code contains the @code{main} function and the
@code{GameServer} class declaration and implementation.
The @code{main()} function vends the server's root object and starts the
runloop, while the @code{GameServer} class adopts the @code{GameServer}
protocol. The class also implements methods that initialise and
deallocate the root object's instance variables (dictionaries that hold
player information).
@example
#include <Foundation/Foundation.h>
#include "GameServer.h"
#include "GameClient.h"
/*
* GameServer class declaration:
* Adopt the GameServer protocol and declare
* GameServer instance variables.
*/
@@interface GameServer : NSObject <GameServer>
@{
NSMutableDictionary *delayUntil; // Delays to re-joining GameServer.
NSMutableDictionary *currentPlayers; // Proxies to each client.
NSMutableDictionary *hasWon; // Success in game for each player.
@}
@@end
/*
* GameServer class implementation.
*/
@@implementation GameServer
/* Initialise GameServer's instance variables. */
- (id) init
@{
self = [super init];
if (self != nil)
@{
/*
* Create a dictionary for a maximum of
* 10 named players that will hold a
* re-joining time delay.
*/
delayUntil = [[NSMutableDictionary alloc]
initWithCapacity: 10];
/*
* Create a dictionary that will hold the
* names of these players and a proxy for
* the received client objects.
*/
currentPlayers = [[NSMutableDictionary alloc]
initWithCapacity: 10];
/*
* Create a dictionary that will record
* a win for any of these named players.
*/
hasWon = [[NSMutableDictionary alloc]
initWithCapacity: 10];
@}
return self;
@}
/* Release GameServer's instance variables. */
- (void) dealloc
@{
RELEASE(delayUntil);
RELEASE(currentPlayers);
RELEASE(hasWon);
[super dealloc];
@}
/*
* Implement mayJoin:: as declared in the protocol.
* Adds the client to the list of current players.
* Each player is represented at the server by both
* name and by proxy to the received client object.
* A player cannot join the game if they are already playing,
* or if joining has been delayed until a later date.
*/
- (BOOL) mayJoin: (id)client asPlayer: (NSString*)name
@{
NSDate *delay; // The time a player can re-join the game.
NSString *aMessage;
if (name == nil)
@{
NSLog(@@"Attempt to join nil user");
return NO;
@}
/* Has the player already joined the game? */
if ([currentPlayers objectForKey: name] != nil)
@{
/* Inform the client that they cannot join. */
aMessage = @@"\nSorry, but you are already playing GameServer!\n";
[client clientMessage: aMessage];
return NO;
@}
/* Get the player's time delay for re-joining. */
delay = [delayUntil objectForKey: name];
/*
* Can the player join the game? Yes if there is
* no restriction or if the time delay has passed;
* otherwise no, they cannot join.
*/
if (delay == nil || [delay timeIntervalSinceNow] <= 0.0)
@{
/* Remove the old restriction on re-joining the game. */
[delayUntil removeObjectForKey: name];
/* Add the player to the list of current players. */
[currentPlayers setObject: client forKey: name];
[hasWon setObject: @@"NO" forKey: name]; // They've not won yet.
/* Inform the client that they have joined the game. */
aMessage = @@"\nWelcome to GameServer\n";
[client clientMessage: aMessage];
return YES;
@}
else
@{
/* Inform the client that they cannot re-join. */
aMessage = @@"\nSorry, you cannot re-join GameServer yet.\n";
[client clientMessage: aMessage];
return NO;
@}
@}
/*
* Implement startGame: as declared in the protocol.
* Simply ask the player if they want to win, and get
* there reply.
*/
- (int) startGame: (NSString *)name
@{
NSString *aMessage;
id client;
int reply;
client = [currentPlayers objectForKey: name];
aMessage = @@"\nDo you want to win this game? (Y/N <RET>) ... ";
[client clientMessage: aMessage];
reply = [client clientReply];
if(reply == 'y' || reply == 'Y')
[hasWon setObject: @@"YES" forKey: name]; // They win.
else [hasWon setObject: @@"NO" forKey: name]; // They loose.
return 0;
@}
/*
* Implement endGame: as declared in the protocol.
* Removes a player from the game, and either sets
* a restriction on the player re-joining or removes
* the current restriction.
*/
- (BOOL) endGame: (NSString*)name
@{
id client;
NSString *aMessage, *yesOrNo;
NSDate *now, *delay;
NSTimeInterval twoHours = 2 * 60 * 60; // Seconds in 2 hours.
if (name == nil)
@{
NSLog(@@"Attempt to end nil user");
return NO;
@}
now = [NSDate date];
delay = [now addTimeInterval: twoHours];
client = [currentPlayers objectForKey: name];
yesOrNo = [hasWon objectForKey: name];
if ([yesOrNo isEqualToString: @@"YES"]) // Has player won?
@{
/*
* Player wins, no time delay to re-joining the game.
* Remove any re-joining restriction and send
* a message to the client.
*/
[delayUntil removeObjectForKey: name];
aMessage = @@"\nWell played: you can re-join GameServer at any time.\n";
[client clientMessage: aMessage];
@}
else // Player lost
@{
/*
* Set a time delay for re-joining the game,
* and send a message to the client.
*/
[delayUntil setObject: delay forKey: name];
aMessage = @@"\nYou lost, but you can re-join GameServer in 2 hours.\n";
[client clientMessage: aMessage];
@}
/* Remove the player from the current game. */
[currentPlayers removeObjectForKey: name];
[hasWon removeObjectForKey: name];
return YES;
@}
@@end // End of GameServer class implementation
/*
* The main function of the server program simply
* vends the root object and starts the runloop.
*/
int main(int argc, char** argv)
@{
CREATE_AUTORELEASE_POOL(pool);
GameServer *server;
NSConnection *connXion;
server = AUTORELEASE([GameServer new]);
connXion = [NSConnection defaultConnection];
[connXion setRootObject: server];
[connXion registerName: @@"JoinGame"];
[[NSRunLoop currentRunLoop] run];
RELEASE(pool);
return 0;
@}
@end example
To summarise the code at the server:
@itemize @bullet
@item We vend the server's root object and start a runloop,
allowing clients to connect with the server.@*@*
@item When we receive a proxy for a client object, we communicate
with that client using methods declared in the @code{ClientServer}
protocol.@*@*
@item We create three dictionary objects, each referenced by player
name. @code{currentUsers} holds proxies for each of the current
players; @code{delayUntil} holds times when each player can re-join
the game; and @code{hasWon} holds a string for each player, which is
set to "YES" if the player wins.@*@*
@item When the game is in progress, the server can alter the state of
each client object to reflect the success of each player.
@end itemize
I hope you managed to understand most of the code in this example. If
you are reading the on-screen version, then you can copy and paste the
code to suitably named files, create makefiles, and then make and run
each program. What message is displayed if you immediately try to
re-join a game after loosing? And after winning?
@i{Exercise: Modify the server code so that the server records the
number of wins for each player, and displays this information at both
the start and end of each game.}
@section Language Support for Distributed Objects
Objective-C provides special 'type' qualifiers that can be used in a
protocol to control the way that message arguments are passed between
remote processes, while at run time, the run-time system transparently
uses what is known as 'forward invocation' to forward messages to a
remote process.
@subsection Protocol Type Qualifiers
@cindex protocol type qualifiers
@cindex in, out, and inout type qualifiers
@cindex out, type qualifier
@cindex oneway, type qualifier
@cindex bycopy and byref type qualifiers
When message arguments are passed by value then the receiving method can
only alter the copy it receives, and not the value of the original
variable. When an argument is passed by reference (as a pointer), the
receiving method has access to the original variable and can alter that
variable's data. In this case the argument is effectively passed 'in' to
the method, and then passed 'out' of the method (on method return).
When an argument is passed by reference to a remote object, the network
must handle this two-way traffic, whether or not the remote object
modifies the received argument.
Type qualifiers can be used in a protocol to control the way these
messages are handled, and to indicate whether or not the sending process
will wait for the remote process to return.
@itemize @bullet
@item The @b{oneway} qualifier is used in conjunction with a
@code{void} return type to inform the run-time system that the sending
process does not need to wait for the receiving method to return (known
as 'asynchronous' messaging). The protocol declaration for the receiving
method would look something like this:@*@*
@code{- (@b{oneway} void)noWaitForReply;}@*@*
@item The @b{in, out } and @b{inout} qualifiers can be used with pointer
arguments to control the direction in which an argument is passed. The
protocol declaration for the receiving methods would look something like
this:@*
@example
/*
* The value that 'number' points to will be passed @b{in} to the remote process.
* (No need to return the argument's value from the remote process.)
*/
@code{- setValue: (@b{in} int *)number;}
/*
* The value that 'number' points to will be passed @b{out} of the remote process.
* (No need to send the argument's value to the remote process.)
*/
@code{- getValue: (@b{out} int *)number;}
/*
* The value that 'number' points to is first passed @b{in} to the remote
* process, but will eventually be the value that is passed @b{out} of the
* remote process. (Send and return the argument's value.)
*/
@code{- changeValue: (@b{inout} int *)number;}
@end example
@item The @b{bycopy} and @b{byref} qualifiers can be used in a protocol
when the argument or return type is an object.@*@*
An object is normally passed by reference and received in the remote
process as a proxy. When an object is passed by copy, then a copy of
the object will be received in the remote process, allowing the remote
process to directly interact with the copy. Protocol declarations would
look something like this:@*
@example
/*
* Copy of object will be received in the remote process.
*/
- sortNames: (@b{bycopy} id)listOfNames;
/*
* Copy of object will be returned by the remote process.
*/
- (@b{bycopy} id)returnNames;
@end example
By default, large objects are normally sent @b{byref}, while small
objects like @code{NSStrings} are normally sent @b{bycopy}, but you
cannot rely on these defaults being adopted and should explicitly state
the qualifier in the protocol.@*@*
The @b{bycopy} qualifier can also be used in conjunction with the
@b{out} qualifier, to indicate that an object will be passed @b{out} of
the remote process by copy rather than by proxy (no need to send the
object).@*
@example
/*
* The object will not be received in the remote process, but the object
* will be returned @b{bycopy}.
*/
- sortAndReturn: (@b{bycopy out} id *)listOfNames;
@end example
You should be aware that some classes ignore the @b{bycopy} qualifier
and the object will be sent by reference. The @b{bycopy} qualifier will
also be ignored if the remote process does not have the class of the
object in its address space, since an object's instance variables are
accessed through the object's methods.@*@*
When a copy of an object is sent to a remote process, only the object's
instance variables are sent and received (an object's methods exist in
the address space of the object's class, not in the address space of the
individual object).
@end itemize
@subsection Message Forwarding
@cindex message forwarding, distributed objects
@cindex forward invocation, distributed objects
When a proxy forwards a message to a remote object, the GNUstep run-time
extensions automatically implement what is known as 'forward
invocation'. At run-time, the message received at the proxy is
automatically re-packaged and sent to the proxy's
@code{forwardInvocation:} method. This method determines whether or not
a remote object exists that can respond to the received message,
forwarding the message on (or not), depending on the reply.@*
While this handling of messages by the proxy is transparent to the
distributed objects programmer, any object can implement forward
invocation, allowing it to pass on messages for which it has no
responding method. Forward invocation is discussed in more detail in the
next chapter.
@section Error Checking
@cindex error checking, distributed objects
@cindex distributed objects, error checking
When dealing with distributed objects your code must be able to handle
the following situations: failure to vend the server object, exceptions
raised at run-time, and failure of the network connection.
@subsection Vending the Server Object
When vending the server object, your code must be able to handle the
situation in which the network does not accept the proposed registered
name for the server.
@subsection Catching Exceptions
There are two situations to consider.
@itemize @bullet
@item An @code{NSPortTimeoutException} is raised.@*@*
This exception is raised if a message takes too long to arrive at the
remote process, or if a reply takes too long to return. This will happen
if the remote process is busy, has hung, or if there is a problem with
the network. The best way to handle the exception is to close the
connection to the remote process.@*@*
@item An exception is raised in the remote process while the remote
process is executing a method.@*@*
In most cases you can deal directly with these exceptions in the process
in which they were raised; i.e. without having to consider the network
connection itself.
@end itemize
@subsection The Connection Fails
You can register an observer object to receive a notification, in the
form of a @code{connectionDidDie} message, when a registered connection
fails. The argument to this message will be an @code{NSNotification}
object that returns the failed connection when it receives an
@code{object} message.
To receive this 'notification' the observer must implement the
@code{connectionDidDie} method, but can be an instance of any class. The
observer can then handle the failure gracefully, by releasing any
references to the failed connection and releasing proxies that used the
connection. Registering an object to receive this notification is
described in more detail in the @code{NSConnection} class documentation.
@subsection GameServer Example with Error Checking
Earlier on in this section we looked at an example client/server program
called GameServer, and you will find a further example of this program,
with additional error checking, in Appendix B.

View file

@ -0,0 +1,185 @@
@paragraphindent 0
@node Examples
@appendix Example Objective-C Code
@cindex example Objective-C code
@c /* Add example code to this file as it becomes available */
@section A Simple Telephone Directory
In the 'Distributed Objects' chapter, it was left as an exercise to
prepare code for a simple client/server telephone directory. Below is
one implementation that you can compare with your own version.
If you are reading the on-screen version of this manual, then you can
copy and paste the code to suitably named files, and then make and run
each program. The directory only stores the telephone numbers of two
people: Jack and Jill.
To use the telephone directory first run the server and then the client,
passing either Jack or Jill as a command line argument. If you pass any
other name then the number will be displayed as 'Number not found'.
@subsection The Makefiles
@example
# The Client makefile, saved as GNUmakefile
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = RunClient
RunClient_OBJC_FILES = Client.m
include $(GNUSTEP_MAKEFILES)/tool.make
# End of client makefile
# The Server makefile, saved as GNUmakefile
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = RunServer
RunServer_OBJC_FILES = Server.m
include $(GNUSTEP_MAKEFILES)/tool.make
# End of server makefile
@end example
@subsection The Protocol Header File
@example
/*
* TelephoneDirectory protocol, saved as TelephoneDirectory.h.
* This file must be included at both client and server.
*/
@@protocol TelephoneDirectory
- (char *) teleNumber: (char *)personName;
@@end
@end example
@subsection Code at the Client
@example
/*
* This #include line is generally present in all Objective-C
* source files that use GNUstep. The Foundation.h header file
* includes all the other standard header files you need.
*/
#include <Foundation/Foundation.h>
/* Include the TelephoneDirectory protocol header file */
#include "TelephoneDirectory.h"
/*
* The main() function: Get the telephone number for
* 'personName' from the server registered as 'DirectoryServer'.
*/
int main(int argc, char *argv[])
@{
char *personName = argv[1];
char *returnedNumber;
id<TelephoneDirectory> proxyForDirectory;
CREATE_AUTORELEASE_POOL(pool);
proxyForDirectory = (id<TelephoneDirectory>) [NSConnection
rootProxyForConnectionWithRegisteredName:
@@"DirectoryServer"
host: @@"*"];
if(proxyForDirectory == nil)
printf("\n** WARNING: NO CONNECTION TO SERVER **\n");
else printf("\n** Connected to server **\n");
if(argc == 2) // Command line name entered
@{
returnedNumber = (char *)[proxyForDirectory teleNumber: personName];
printf("\n%s%s%s%s%s\n", "** (In client) The telephone number for ",
personName, " is:",
returnedNumber, " **");
@}
else printf("\n** No name entered **\n");
printf("\n%s\n\n", "** End of client program **");
RELEASE(pool);
return 0;
@}
@end example
@subsection Code at the Server
@example
#include <Foundation/Foundation.h>
/* Include the TelephoneDirectory protocol header file */
#include "TelephoneDirectory.h"
/*
* Declare the TelephoneDirectory class that
* implements the 'teleNumber' instance method.
*/
@@interface TelephoneDirectory : NSObject <TelephoneDirectory>
@@end
/*
* Define the TelephoneDirectory class
* and the instance method (teleNumber).
*/
@@implementation TelephoneDirectory : NSObject
- (char *) teleNumber: (char *) personName
@{
if (strcmp(personName, "Jack") == 0) return " 0123 456";
else if (strcmp(personName, "Jill") == 0) return " 0456 789";
else return " Number not found";
@}
@@end
/*
* The main() function: Set up the program
* as a 'Distibuted Objects Server'.
*/
int main(void)
@{
CREATE_AUTORELEASE_POOL(pool);
/* Declare and define the telephoneDirectory object */
TelephoneDirectory *teleDirectory = [[TelephoneDirectory alloc] init];
/*
* Get the default NSConnection object,
* or create a new one if none exists.
*/
NSConnection *connXion = [NSConnection defaultConnection];
/*
* Set the responding server object to be
* the root object for this connection.
*/
[connXion setRootObject: teleDirectory];
/*
* Try to register a name for the NSConnection,
* and report an error if this is not possible.
*/
if ([connXion registerName: @@"DirectoryServer"] == NO)
@{
NSLog(@@"Unable to register as 'DirectoryServer'");
NSLog(@@"Perhaps another copy of this program is running?");
exit(1);
@}
else NSLog(@@"\n** Managed to register connection as 'DirectoryServer' **\n");
/* Start the current runloop. */
[[NSRunLoop currentRunLoop] run];
RELEASE(pool);
return 0;
@}
@end example
@section GameServer with Error Checking
In the 'Distributed Objects' chapter, code was listed at the client and
server for an example GameServer. The code is reproduced here, but with
additional error checking for: failure to vend the server object,
exceptions raised at run-time, and failure of the network connection.
*** Code to be added here ***

View file

@ -0,0 +1,27 @@
include $(GNUSTEP_MAKEFILES)/common.make
GNUSTEP_MAKEINFO_FLAGS = -D NO-TEXI2HTML
DOCUMENT_NAME = manual
manual_TEXI_FILES = \
manual.texi \
foreword.texi \
Introduction.texi \
ObjcLanguage.texi \
WritingNewClasses.texi \
WorkingWithObjects.texi \
DistributedObjects.texi \
AdvancedTopics.texi \
Glossary.texi \
ExampleCode.texi \
GNUstepMake.texi \
ObjcAndJava.texi \
JavaAndGuile.texi
manual_DOC_INSTALL_DIR = Developer/Base/ProgrammingManual
include $(GNUSTEP_MAKEFILES)/documentation.make

View file

@ -0,0 +1,226 @@
@node Make
@appendix Using the GNUstep Make Package
@cindex GNUstep Make package
@cindex Make package, GNUstep
Reference/doc on the GNUstep make package; mainly examples of various
types of projects.
@section Makefile Contents
@paragraphindent 0
@b{Note. Type @code{man make} for assistance.}
Make files comprise four key content types:
@itemize @bullet
@item
@b{Comments}
@code{#} prefixes comments.
@item
@b{Macros}
@code{SRC=main.m} assigns a macro that is implemented as:@code{gcc $(SRC)}
and is interpreted as:
@code{gcc main.m}
@item
@b{Explicit rules}
Explicit rules are used to indicate which files depend upon supporting files and
the commands required for their compilation:
@example
targetfile : sourcefiles
commands
@end example
A Tab precedes each command that must be implemented on the source files in order
to create the target file:
@example
main: main.m List.h
gcc -o main main.m List.h
@end example
@item
@b{Implicit rules}
Implicit rules broadly echo explicit variants but do not specify commands, rather the
extensions indicate which commands are performed:
@code{servertest.o: servertest.c io.h}
@*
is interpreted as:
@*
@code{$(CC) $(CFLAGS) -c servertest.c io.h}
@end itemize
@subsection Makefile Example
@example
# The following two lines force the standard make to recognize the
# Objective-C .m suffix.
.SUFFIXES: .o .m
.m.o:
$(CC) -c $(CFLAGS) $<
# Macro declarations
CC = gcc
CFLAGS = -g
LIBS = -lobjc
SRC=main.m Truck.m Station.m Vehicle.m
OBJ=main.o Truck.o Station.o Vehicle.o
# Explicit rules
hist: $(OBJ)
$(CC) $(CFLAGS) -o main $(OBJ) $(LIBS)
# Implicit rules
Truck.o: Truck.h Truck.m
Station.o: Truck.h Station.h Station.m
Vehicle.o: Truck.h Vehicle.h Vehicle.m
main.o: Station.h Vehicle.h
@end example
@subsection Makefile Structure
The following Makefile defines a project:
@example
#
# A GNUmakefile
#
# Include the common variables
include $(GNUSTEP_MAKEFILES)/common.make
# Build an Objective-C program
OBJC_PROGRAM_NAME = simple
# Objective-C files requiring compilation
simple_OBJC_FILES = simple.m
-include GNUmakefile.preamble
# Include in the rules for making Objective-C programs
include $(GNUSTEP_MAKEFILES)/objc.make
-include GNUmakefile.postamble
@end example
To compile a package that uses the Makefile Package, type @code{make} in the
top-level directory of the package. A non-GNUstep Objective-C file may be
compiled by adding @code{-lobjc on} at the command line.
@subsection Debug and Profile Information
By default the Makefile Package does not flag the compiler to generate debugging
information that is generated by typing:
@code{make debug=yes}
This command also causes the Makefile Package to turn off optimization. It is
therefore necessary to override the optimization flag when running Make if both
debugging information and optimization is required. Use the variable OPTFLAG to
override the optimization flag.
By default the Makefile Package does not instruct the compiler to create profiling
information that is generated by typing:
@code{make profile=yes}
@sp 1
@subsection Static, Shared and DLLs
By default the Makefile Package generates a shared library if it is building a
library project type, and it will link with shared libraries if it is building
an application or command-line tool project type. To tell the Makefile Package
not to build using shared libraries but using static libraries instead, type:
@code{make shared=no}
This default is only applicable on systems that support shared libraries;
systems that do not support shared libraries will always build using static
libraries. Some systems support DLLs that are a form of shared libraries; on
these systems DLLs are built by default unless the Makefile Package is told to
build using static libraries instead.
@section Project Types
Projects are divided into different types. To create a project of a specific
type, a make file is specified:
@code{include $(GNUSTEP_MAKEFILES)/application.make}
Each project type is independent, and if you want to create two project types in
the same directory (e.g. a tool and a Java program), include both the desired
make files in your main Make file.
@itemize @bullet
@item
Aggregate - aggregate.make
An Aggregate project holds several sub-projects that are of any valid
project type (including the Aggregate type). The only project variable is the
SUBPROJECTS variable:
@code{Aggregate project: SUBPROJECTS}
SUBPROJECTS defines the directory names that hold the sub-projects that the
Aggregate project should build.
@item Graphical Applications - application.make
An application is an Objective-C program that includes a GUI component, and by
default links in all the GNUstep libraries required for GUI development, such as
the Base and GUI libraries.
@item Bundles - bundle.make
A bundle is a collection of resources and code that can be used to enhance an
existing application or tool dynamically using the NSBundle class from the
GNUstep base library.
@item Command Line C Tools - ctool.make
A ctool is a project that uses only C language files. Otherwise it is similar to
the ObjC project type.
@item Documentation - documentation.make
The Documentation project provides rules to use various types of documentation
such as texi and LaTeX documentation, and convert them into finished
documentation like info, PostScript, HTML, etc.
@item Frameworks - framework.make
A Framework is a collection of resources and a library that provides common code
that can be linked into a Tool or Application. In many respects it is similar to
a Bundle.
@item Java - java.make
This project provides rules for building java programs. It also makes it easy to
make java projects that interact with the GNUstep libraries.
@item Libraries - library.make
The Makefile Package provides a project type for building libraries that may be
static, shared, or dynamic link libraries (DLLs). The latter two variants are
supported only on some platforms.
@end itemize

View file

@ -0,0 +1,36 @@
@paragraphindent 0
@node Glossary
@appendix Glossary
@cindex glossary
@c /* Empty glossary (to be completed). */
Object
Class
Inheritance
Polymorphism
Encapsulation
Invoke
Method
Makefile

View file

@ -0,0 +1,199 @@
@paragraphindent 0
@node Introduction
@chapter Introduction
The aim of this manual is to introduce you to the Objective-C language and the GNUstep development environment. The manual is organised to give you a tutorial introduction to the language, by using examples whenever possible, rather than providing a lengthy description of the language.
While Objective-C is not a difficult language to learn or use, some of the terms may be unfamiliar, especially to those that have not programmed using an object-oriented programming language before. Whenever possible, concepts will be explained in simple terms rather than in more advanced programming terms. So to start I'll give you a brief description of object-oriented programming, the Objective-C language and the GNUstep development environment.
The descriptions are not authoritative, and given only as a grounding for the topics that follow.
@section What is Object-Oriented Programming?
@cindex object-oriented programming
There are several object-oriented (OO) programming languages in common use today and you have probably heard of some of them: C++ and Java for example, and of course Objective-C. OO languages all have one thing in common: they allow you to design and write programs in a different way than if you used a traditional procedural language like C or Pascal.
Procedural languages provide the programmer with basic building blocks that consist of data types, (integers, characters, float etc) and functions that act on that data. This forces the program designer to design the program using these same building blocks. Quite often this requires quite a leap in imagination between what the program must do and how it can be implemented.
Object-oriented languages allow the program designer to think in terms of building blocks that are closer to what the program will actually do. Rather than think in terms of data and functions that act on that data, OO languages provide you with objects and the ability to send messages to those objects. Objects are, in a sense, like mini programs that can function on their own when requested by the program or even another object.
For example, an object may exist that can draw a rectangle in a window; all you need to do as a programmer is send the appropriate messages to that object. The messages could tell the object the size of the rectangle and position in the window, and of course tell the object to draw itself. Program design and implementation is now reduced to sending messages to the appropriate objects rather than calling functions to manipulate data.
@subsection Some Basic OO Terminology
@cindex basic OO terminology
OO languages add to the vocabulary of more traditional programming languages, and it may help if you become familiar with some of the basic terms before jumping in to the language itself.
Objects
As stated previously, an object is one of the basic building blocks in OO programming. An object can receive messages and then act on these messages to alter the state of itself (the size and position of a rectangle object for example). In software an object consists of instance variables (data) that represent the state of the object, and methods (like C functions) that act on these variables in response to messages.
Rather than 'calling' one of its methods, an object is said to 'perform' one of its methods in response to a message. (A method is known as a 'member function' in C++.)
Classes
All objects of the same type are said to be members of the same class. To continue with the rectangle example, every rectangle could belong to a rectangle class, where the class defines the instance variables and the methods of all rectangles.
A class definition by itself does not create an object but instead acts like a template for each object in that class. When an object is created an 'instance' of that class is said to exist. An instance of a class (an object) has the same data structure (instance variables) and methods as every other object in that class.
Inheritance
When you define a new class you can base it on an existing class. The new class would then 'inherit' the data structure and methods of the class that you based it on. You are then free to add instance variables and methods, or even modify inherited methods, to change the behavior of the new class (how it reacts to messages).
The base class is known as the 'superclass' and the new class as the 'subclass' of this superclass. As an example, there could be a superclass called 'shapes' with a data structure and methods to size, position and draw itself, on which you could base the rectangle class.
Polymorphism
Unlike functions in a procedural program such as C, where every function must have a unique name, a method (or instance variable) in one class can have the same name as that in another class.
This means that two objects could respond to the same message in completely different ways, since identically named methods may do completely different things. A draw message sent to a rectangle object would not produce the same shape as a draw message sent to a circle object.
Encapsulation
An object hides its instance variables and method implementations from other parts of the program. This encapsulation allows the programmer that uses an object to concentrate on what the object does rather than how it is implemented.
Also, providing the interface to an object does not change (the methods of an object and how they respond to received messages) then the implementation of an object can be improved without affecting any programs that use it.
Dynamic Typing and Binding
Due to polymorhism, the method performed in response to a message depends on the class (type) of the receiving object. In an OO program the type, or class, of an object can be determined at run time (dynamic typing) rather than at compile time (static typing).
The method performed (what happens as a result of this message) can then be determined during program execution and could, for example, be determined by user action or some other external event. Binding a message to a particular method at run time is known as dynamic binding.
@section What is Objective-C?
@cindex what is Objective-C?
@cindex Objective-C, what is?
Objective-C is a powerful object-oriented (OO) language that extends the procedural language ANSI C with the addition of a few keywords and compiler directives, plus one syntactical addition (for sending messages to objects). This simple extension of ANSI C is made possible by an Objective-C runtime library (libobjc) that is generally transparent to the Objective-C programmer.
During compilation of Objective-C source code, OO extensions in the language compile to C function calls to the runtime library. It is the runtime library that makes dynamic typing and binding possible, and that makes Objective-C a true object-oriented language.
Since Objective-C extends ANSI C with a few additional language constructs (the compiler directives and syntactical addition), you may freely include C code in your Objective-C programs. In fact an Objective-C program may look familiar to the C programmer since it is constructed using the traditional @code{main} function.
@example
#include <stdio.h>
#include <objc/objc.h>
int main (void)
@{
/* Objective C and C code */
return(0);
@}
@end example
Objective-C source files are compiled using the standard GNU @b{gcc} compiler. The compiler recognises Objective-C source files by the .m file extension, C files by the .c extension and header files by the .h extension.
As an example, the command @b{$gcc -o testfile testfile.m -lobjc} would compile the Objective-C source file @code{testfile.m} to an executable named @code{testfile}. The @code{-lobjc} compiler option is required for linking an Objective-C program to the runtime library.
The GNUstep @b{make} utility provides an alternative (and simple) way to compile large projects, and this useful utility is discussed in the next section.
@section What is GNUstep?
@cindex what is GNUstep?
@cindex GNUstep, what is?
GNUstep is an object-oriented development environment that provides the Objective-C programmer with a range of utilities and libraries for building large, cross-platform, applications and tools.
This manual does not discuss the full functionality of GNUstep but concentrates on using the GNUstep base library to create non-graphical programs, and the GNUstep @b{make} utility to compile these programs. Further information about GNUstep can be found at @url{http://www.gnustep.org}.
@subsection GNUstep Base Library
@cindex GNUstep base library
The GNUstep base library contains a powerful set of non-graphical Objective-C classes that can readily be used in your programs. At present there are approximately 70 different classes available, including classes to handle strings and arrays, dates and times, distributed objects, URLs and file systems (to name but a few).
Classes in the base library are easily identified since they begin with the upper case characters 'NS', as in @code{NSString}. Some examples in this manual use classes from the base library, but for complete documentation on the base library visit the GNUstep web site at @url{http://www.gnustep.org}.
@subsection GNUstep Make Utility
@cindex GNUstep make utility
The GNUstep @b{make} utility is the GNU version of the UNIX make utility. So what does it do? It simplifies the process of building (compiling and linking) a large project. You simply type @b{make} at the command prompt and the make utility takes care of file dependencies, only re-compiling source files that have changed, or that depend on files that have changed, since the last 'make' (a header file for example).
Before using @b{make} you must first create a 'makefile' that lists all the files and file dependencies in your project. The easiest way to do this is to copy an existing makefile and change it to suit your own project.
The make utility will be used to build the Objective-C examples shown in this manual, and when an example can be compiled then the makefile will also be shown. Further information about makefiles and the make utility can be found in Appendix C.
@section Building Your First Objective-C Program
@cindex your first Objective-C program
The following example will show you how to create and compile an Objective-C program. The example simply displays a text message on the screen, and there are easier ways to to do this, but the example does demonstrate a number of object-oriented features of Objective-C, and also demonstrates the use of @b{make} to compile an Objective-C program.
@enumerate
@item
Create a new project directory to hold your project.@*@*
@item
Create the following Objective-C source code using your favourite text
editor and save it in the project directory with the filename @code{source.m}.
@example
#include <stdio.h>
/*
* The next #include line is generally present in all Objective-C
* source files that use GNUstep. The Foundation.h header file
* includes all the other standard header files you need.
*/
#include <Foundation/Foundation.h>
/*
* Declare the Test class that implements the class method (classStringValue).
*/
@@interface Test
+ (const char *) classStringValue;
@@end
/*
* Define the Test class and the class method (classStringValue).
*/
@@implementation Test
+ (const char *) classStringValue;
@{
return "This is the string value of the Test class";
@}
@@end
/*
* The main() function: pass a message to the Test class
* and print the returned string.
*/
int main(void)
@{
printf("%s\n", [Test classStringValue]);
return 0;
@}
@end example
The text between comment markers (/* */) is ignored by the compiler but indicates to someone reading the source file what each part of the program does. The program is an example of a (class) method responding to a message. Can you see how it works?@*@*
A message is sent to the @code{Test} class as an argument to @code{printf()}, requesting the string value of that class. The @code{Test} class performs its @code{classStringValue} method in response to this message and returns a string that is finally printed. No object is created in this program since a class method does not require an instance of a class in order to respond to a message.@*@*
You will learn more about class methods in the next chapter.@*@*
@item
Now create the makefile, again using your favourite text editor, and save it in the same project directory with the filename @code{GNUmakefile}.
@example
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = LogTest
LogTest_OBJC_FILES = source.m
include $(GNUSTEP_MAKEFILES)/tool.make
@end example
If you look at the makefile above you will notice the two lines that tell the make utility to build a tool with the filename @code{LogTest} from the Objective-C source file @code{source.m}. You could copy and modify this makefile for later projects you may have: just change the tool name and list the new source files.@*@*
The two 'include' lines are just a way of keeping your makefile simple, by including two 'ready-made' makefiles that someone else created.@*@*
@item
You can now compile the project using make. At the system command prompt, change to the project directory and enter the @b{make} command.@*@*
@item
Run the program (for Linux enter @b{./LogTest} at the command prompt). The message "This is the string value of the Test class" will be displayed (assuming there were no errors).
@end enumerate
You have now compiled and run you first Objective-C program. Hungry for more? Then read on.

View file

@ -0,0 +1,8 @@
@node Java and Guile
@appendix Programming GNUstep in Java and Guile
@cindex Java and Guile, programming GNUstep
Other appendices might explain how to use GNUstep from Java and from
guile, with examples but without becoming a full reference about it.
For that, more complete documentation should be/is bundled with the
interfaces.

View file

@ -0,0 +1,218 @@
@node Obj-C and Java
@appendix Differences and Similarities Between Objective-C and Java
@cindex Objective-C and Java, differences and similarities
@cindex differences and similarities, Objective-C and Java
@paragraphindent 0
This appendix explains the differences/similarities between Objective-C
and Java. It has nothing to do with JIGS, but is included to help people who want to learn Objective-C and know Java
already.
@section General
@itemize @bullet
@item
C programmers may learn Objective-C in hours (though real expertise
obviously takes much longer).
@item
Java has global market acceptance.
@item
Objective-C is a compiled OO programming language.
@item
Java is both compiled and interpreted and therefore does not offer
the same run-time performance as Objective-C.
@item
Objective-C features efficient, transparent Distributed Objects.
@item
Java features a less efficient and less transparent Remote Machine
Interface.
@item
Objective-C has basic CORBA compatibility through official C bindings,
and full compatibility through unofficial Objective-C bindings.
@item
Java has CORBA compatibility through official Java bindings.
@item
Objective-C is portable across heterogeneous networks by virtue of a
near omnipresent compiler (gcc).
@item
Java is portable across heterogeneous networks by using client-side JVMs
that are software processors or runtime environments.
@end itemize
@section Language
@itemize @bullet
@item
Objective-C is a superset of the C programming language, and may
be used to develop non-OO and OO programs. Objective-C provides
access to scalar types, structures and to unions, whereas Java
only addresses a small number of scalar types and everything else
is an object. Objective-C provides zero-cost access to existing
software libraries written in C, Java requires interfaces to be
written and incurs runtime overheads.
@item
Objective-C is dynamically typed but also provides static typing.
Java is statically types, but provides type-casting mechanisms to
work around some of the limitations of static typing.
@item
Java tools support a convention of a universal and distributed
name-space for classes, where classes may be downloaded from
remote systems to clients. Objective-C has no such conventions
or tool support in place.
@item
Using Java, class definitions may not be divided or extended through
the addition of logical groupings. Objective-C's provides categories
as a solution to this problem.
@item
Objective-C provides delegation (the benefits of multiple inheritance
without the drawbacks) at minimal programming cost. Java requires
purpose written methods for any delegation implemented.
@item
Java provides garbage collection for memory management. Objective-C
provides manual memory management, reference counting, and garbage
collection.
@item
Java provides interfaces, Objective-C provides protocols.
@end itemize
@section Source Differences
@itemize @bullet
@item
Objective-C is based on C, and the OO extensions are comparable with
those of Smalltalk. The Java syntax is based on the C++ programming
language.
@item
The object (and runtime) models are comparable, with Java's
implementation having a subset of the functionality of that
of Objective-C.
@end itemize
@section Compiler Differences
@itemize @bullet
@item
Objective-C compilation is specific to the target system/environment,
and because it is an authentic compiled language it runs at higher
speeds than Java.
@item
Java is compiled into a byte stream or Java tokens that are interpreted
by the target system, though fully compiled Java is possible.
@end itemize
@section Developer's Workbench
@itemize @bullet
@item
Objective-C is supported by tools such as GNUstep that provides
GUI development, compilation, testing features,
debugging capabilities, project management and database access.
It also has numerous tools for developing projects of different
types including documentation.
@item
Java is supported by numerous integrated development environments
(IDEs) that often have their origins in C++ tools.
Java has a documentation tool that parses source code and creates
documentation based on program comments. There are similar features
for Objective-C.
@item
Java is more widely used.
@item
Objective-C may leverage investment already made in C based tools.
@end itemize
@section Longevity
@itemize @bullet
@item
Objective-C has been used for over ten years, and is considered to be
in a stable and proven state, with minor enhancements from time to time.
@item
Java is evolving constantly.
@end itemize
@section Databases
@itemize @bullet
@item
Apple's EOF tools enable Objective-C developers to build object
models from existing relational database tables. Changes in the
database are automatically recognised, and there is no requirement
for SQL development.
@item
Java uses JDBC that requires SQL development; database changes
affect the Java code. This is considered inferior to EOF.
@end itemize
@section Memory
@itemize @bullet
@item
For object allocation Java has a fixed heap whose maximum size
is set when the JVM starts and cannot be resized unless the
JVM is restarted. This is considered to be a disadvantage in
certain scenarios: for example, data read from databases may
cause the JVM to run out of memory and to crash.
@item
Objective-C's heap is managed by the OS and the runtime system.
This can typically grow to consume all system memory (unless
per-process limits have been registered with the OS).
@end itemize
@section Design Stability
@itemize @bullet
@item
Objective-C: A consistent API is provided by the OpenStep software
libraries. Mainstream developers may require knowledge of four to
five APIs, all of which have consistent style/conventions.
@item
Java package APIs are numerous and may use different styles.
@end itemize

View file

@ -0,0 +1,609 @@
@paragraphindent 0
@node Objective-C
@chapter The Objective-C Language
In the previous chapter you were introduced to some basic object-oriented programming terms. This chapter will expand on these terms, and introduce you to some new ones, while concentrating on how they apply to the Objective-C language and the GNUstep base library. First let us look at some non OO additions that Objective-C makes to ANSI C.
@section Non OO Additions
Objective-C makes a few non OO additions to the syntax of the C programming
language that include:
@itemize @bullet
@item
A boolean data type (@code{BOOL}) capable of storing either of the
values @code{YES} or @code{NO}.@*
A @code{BOOL} is a scalar value and can be used like the familiar
@code{int} and @code{char} data types.@*
A @code{BOOL} value of @code{NO} is zero, while @code{YES} is non-zero.
@item
The use of a pair of slashes (@code{//}) to mark text up to the end
of the line as a comment.
@item
The @code{#import} preprocessor directive was added, but its use is deprecated (it still works but it should not be used for new programs).
@end itemize
@section Objects
@cindex objects
@c objects
Object-oriented (OO) programming is based on the notion that a software system can be composed of objects that interact with each other in a manner that parallels the interaction of objects in the physical world.
This model makes it easier for the programmer to understand how software works since it makes programming more intuitive. The use of objects also makes it easier during program design: take a big problem and consider it in small pieces, the individual objects, and how they relate to each other.
Objects are like mini programs that can function on their own when requested by the program or even another object. An object can receive messages and then act on these messages to alter the state of itself (the size and position of a rectangle object in a drawing program for example).
In software an object consists of instance variables (data) that represent the state of the object, and methods (like C functions) that act on these variables in response to messages.
As a programmer creating an application or tool, all you need do is send messages to the appropriate objects rather than call functions that manipulate data as you would with a procedural program.
The syntax for sending a message to an object, as shown below, is one of the additions that Objective-C adds to ANSI C.
@example
[objectName message];
@end example
Note the use of the square [ ] brackets surrounding the name of the object and message.
Rather than 'calling' one of its methods, an object is said to 'perform' one of its methods in response to a message. The format that a message can take is discussed later in this section.
@subsection Id and nil
Objective-C defines a new type to identify an object: @code{id}, a type that points to an object's data (its instance variables). The following code declares the variable 'button' as an object (as opposed to 'button' being declared an integer, character or some other data type).
@example
id button;
@end example
When the button object is eventually created the variable name 'button' will point to the object's data, but before it is created the variable could be assigned the numeric value 0, to indicate to other code that the object does not yet exist.
Objective-C defines a new keyword @code{nil} for this assignment, where @code{nil} is of type @code{id} with the numeric value 0. In the button example, the assignment could look like this:
@example
id button = nil;
@end example
which assigns @code{nil} in the declaration of the variable.
You can then test the value of an object to determine whether the object exists, perhaps before sending the object a message. If the test fails, then the object does not exist and your code can execute an alternative statement.
@example
if (anObject != nil)
... /* send message */
else ... /* do something else */
@end example
The header file @code{objc/objc.h} defines @code{id}, @code{nil}, and other basic types of the Objective-C language. It can be included in your source code with the compiler directive @code{#include <Foundation/Foundation.h>}.
@subsection Messages
@cindex messages
A message in Objective-C is the mechanism by which you pass instructions
to objects. You may tell the object to do something for you, tell it to
change its internal state, or ask it for information.
A message usually invokes a method, causing the receiving object
to respond in some way.
Objects and data are manipulated by sending messages to them.
Like C-functions they have return types, but function specific to the object.
Objects respond to messages that make specific requests.
Message expressions are enclosed in square brackets and include the
receiver or object name and the message or method name along with
any arguments.
To send a message to an object, use the syntax:
@code{[receiver messagename];}
where @code{receiver} is the object.
@sp 1
The run-time system invokes object methods that are specified by messages.
For example, to invoke the display method of the mySquare object the
following message is used:
@code{[mySquare display];}
@sp 1
Messages may include arguments that are prefixed by colons, in which
case the colons are part of the message name, so the following message
is used to invoke the @code{setFrameOrigin::} method:
@code{[button setFrameOrigin: 10.0 : 10.0];}
@sp 1
Labels describing arguments precede colons:
@code{[button setWidth: 20.0 height: 122.0];}
invokes the method named @code{setWidth:height:}
@sp 1
Messages that take a variable number of arguments are of the form:
@code{[receiver makeList: list, argOne, argTwo, argThree];}
@sp 1
A message to nil does NOT crash the application (while in Java messages
to null raise exceptions); the Objective-C application does nothing.
For example:
@code{[nil display];}
will do nothing.
If a message to nil is supposed to return an object, it will return nil.
But if the method is supposed to return something else, then the
return value of that method when invoked on nil, is undefined.
The programmer therefore
needs to avoid using the return value in this instance.
@subsection Polymorphism
@cindex polymorphism
Polymorphism refers to the fact that two different objects may
respond differently to the same message. For example when client
objects receive an alike message from a server object, they may
respond differently. Using Dynamic Binding, the run-time system
determines which code to execute according to the object type.
@section Classes
@cindex classes
@emph{needs to be clearer/readable and say what a class is? also explain
instances!}@*
Objects form groups or classes, and those in the same class hold
the same type of data, and may execute the same methods.
Objects are defined by their originating classes.
Each class compilation sees the creation of a factory or class object
that builds instances of the class. Instances and Objects are synonymous,
and are the components that are operating entities in the running program.
@subsection Inheritance
@cindex inheritance
Most of the programmer's time is spent defining classes.
Inheritance helps reduce coding time by providing a convenient way of
reusing code.
For example, the NSButton class defines data (or instance variables) and methods to create button objects of a certain type, so a subclass of NSButton could be produced to create buttons of another type - which may perhaps have a different border colour. Equally NSTextField can be used to define a subclass that perhaps draws a different border, by reusing definitions and data in the superclass.
Inheritance places all classes in a logical hierarchy or tree
structure that may have the NSObject class at its root.
All classes may have subclasses, and all except the root class
may have superclasses. When a class object creates a new instance,
the new object holds the data for its class, superclass,
and superclasses extending to the root class (typically NSObject).
Additional data may be added to classes so as to provide
specific functions and application logic.
When a new object is created, it is allocated memory space,
and its data in the form of its instance variables are initialised.
The object holds the @code{isa} variable refers to the object's class,
and this also provides access to classes in the object's inheritance
path.
An Objective-C class has an:
@itemize @bullet
@item
interface declaring instance variables, methods and the superclass name.
@item
implementation that defines the class in terms of operational code that
implements the methods.
@end itemize
Typically these entities are confined to separate files
with .h and .m extensions for Interface and Implementation files,
respectively. However they may be merged
into one file, and a single file may implement multiple classes.
@subsection Inheritance of Methods
@cindex inheriting methods
Each new class inherits methods and instance variables from another class. This
results in a class hierarchy with the root class at the core, and every class
(except the root) has a superclass as its parent, and all classes may have
numerous subclasses as their children. Each class therefore is a refinement of
its superclass(es).
@subsection Overriding Methods
@cindex overriding methods
Objects may access methods defined for their class, superclass,
superclass' superclass, extending to the root class.
Classes may be defined with methods that overwrite their namesakes
in ancestor classes. These new methods are then inherited by
subclasses, but other methods in the new class can locate the
overridden methods. Additionally redefined methods may include
overridden methods.
@subsection Abstract Classes
@cindex abstract class
@cindex class, abstract
Abstract classes or abstract superclasses such as NSObject define
methods and instance variables used by multiple subclasses.
Their purpose is to reduce the development effort required to
create subclasses and application structures.
When we get technical, we make a distinction between a pure abstract
class whose methods are defined but instance variables are not,
and a semi-abstract class where instance variables are defined).
An abstract class is not expected to actually produce functional
instances since crucial parts of the code are expected to be
provided by subclasses.
Abstract classes reduce the development effort required to create
subclasses and application structures.
@subsection Class Clusters
@cindex class cluster
@cindex cluster, classes
A class cluster is an abstract base class, and a group of private, concrete
subclasses. It is used to hide implementation details from the programmer
(who is only allowed to use the interface provided by the abstract class),
so that the actual design can be modified (probably optimised) at a later
date, without breaking any code that uses the cluster.
Consider a scenario where it is necessary to create a class hierarchy
to define objects holding different types including @b{chars}, @b{ints},
@b{short}, @b{LongInt}, @b{floats} and @b{doubles}.
Of course, different types could be defined in the same class
since it is possible to @b{cast} or @b{change} them from one to the next.
Their allocated storage differs, however, so it would be inefficient
to bundle them in the same class and to convert them in this way.
The solution to this problem is to use a class cluster:
define an abstract superclass that specifies and declares
components for subclasses, but does not declare instance variables.
Rather this declaration is left to its subclasses, which share the
@b{programmatic interface} that is declared by the abstract superclass.
When you create an object using a cluster interface, you are
given an object of another class - from a concrete class in the cluster.
@section Using the GNUstep Base Library
@cindex GNUstep base library, class documentation
@cindex class documentation for the base library
***
Add something here about using the base library. Some suggestions:
Explain class documentation, what it is (documented class interface that programmers can use), how to use it (the need to read it and comply with the interface methods and arguments), and how to get it (www.gnustep.org).
Also explain some of the terminology, like 'returns a copy of the receiving object'.
***
@section NSObject: The Root Class
@cindex NSObject
@cindex root class
@cindex class, root
NSObject is a root class that provides the framework for all objects,
their interactions, and their integration in the run-time system.
NSObject defines the @code{isa} instance variable that connects
every object with its class
NSObject or an alternative root class:
@itemize @bullet
@item
allocates instances
@item
connects instances to their class
@item
forces the run-time system to discover instances involuntarily.
@end itemize
The NSObject interface is defined as the methods declared by itself, and
those defined by the NSObject protocol. This division ensures that objects
inheriting from other root classes can act as ordinary objects that do not
inherit from NSObject. NSObject provides the facilities for inheriting
classes whose instances are given a behaviour that includes the
ability to:
@itemize @bullet
@item
create objects.
@item
initialize objects.
@item
deallocate objects.
@item
compare objects.
@item
archive objects.
@item
perform methods selected at run-time.
@item
query objects about their methods.
@item
query objects about their position in the inheritance hierarchy.
@item
forward messages to other objects (See Section respondsToSelector).
@end itemize
@subsection Initializing Objects
All objects inherit from the NSObject class, and their initialization requires:
@itemize @bullet
@item
an @code{isa} instance variable that points to a class structure.
@item
initialization of @code{isa} is performed by @code{alloc} and
@code{allocWithZone:} methods that are also used to create
(allocate memory for) new instances of classes.
@end itemize
@section Static Typing
Type checking is good programming practice because it catches errors;
it checks code, but does not change compiled code.
When declaring an object type, static typing permits a class name to
be used instead of an @code{id}. In the
following example Type Checking verifies that the myString object
is an appropriate type.
@example
NSString *myString = anObject;
@end example
Objects can be statically typed as pointers to a class,
by making the pointer explicit (as opposed to hidden using @code{id}).
Static typing permits the compiler to run some obvious checks,
forewarning of such errors as message incompatibilities.
A subclass can be used where a superclass is expected, but not vice-versa.
Formal protocols may be included in type definitions, giving another tier of
type checking to the compiler. Protocol names are included between angle
brackets:
@example
- (id <Formatting>) formattingService;
id <ReferenceCounting,AutoFreeing> specificObject;
@end example
Formal protocols may declare a list of methods that are visible at source and
run-time levels, so objects may introspect themselves at runtime to verify that
they conform to protocols, and the compiler may check for types:
@example
@@protocol ProtocolTitle
declare methods
@@end
@end example
@subsection Type Introspection
Before sending a message you should check that the receiver is the
correct class or has the appropriate method.
The @code{isMemberOfClass:} method defined in the NSObject class
verifies that the receiver is of a specific class:
@example
if ([namedObject isMemberOfClass: specificClass] == YES)
@{
// code here
@}
@end example
The @code{isKindOfClass:} method checks to see if the receiver is
in a specific inheritance path:
@example
if ([namedObject isKindOfClass: specificClass] == YES)
@{
// code here
@}
@end example
@section Working with Class Objects
The compiler creates a class or factory object that instantiates objects
or instances based on the class definitions; class objects are agents
able to instantiate instances in the run-time system. A class object is
not an instance and is without instance variables, though it does holds
static variables and the class instance's prototype also; but it cannot
implement methods for instances of the class.
A class definition may include class methods that are defined for the
class object.
A class object inherits class methods from superclasses,
while instances inherit instance methods. Class objects may receive messages,
and inherit methods from superclasses, but are without instance variables
except those created using the class definition.
@subsection Referring to Class Objects
To return the class version number of the @code{NSString} class
using a method inherited from the NSObject class:
@code{int versionNumber = [NSString version];}
The class name @code{NSString} is that of the class object, which is the receiver
in the above message expression. When not dealing with class objects,
instances and classes are used to obtain the class @code{id}:
@example
id stringClass = [stringObject class];
id mStringClass = [NSMutableString class];
@end example
Class objects may be typed @code{id}, and specifically typed to the Class:
@example
Class stringClass = [stringObject class];
Class mStringClass = [NSMutableString class];
@end example
Class objects are of the type Class, rather like the class name is
used to statically type instances.
@subsection Creating Instances
Class objects create new instances; to use the NSDate class to create
a new @code{NSDate} instance and assign it to the @code{date} variable:
@example
id date;
date = [NSDate alloc];
@end example
The alloc method equates the object's instance variables to zero
with the exception of the @code{isa} variable, and also allocates
memory for them. Complete initialisation of the object however
relies on the @code{init} method that primes 'date' to receive messages:
@code{date = [[NSDate alloc] init];}
The alloc method returns a new instance that implements the
@code{init} method, and like all instances and class objects
it holds at least one method. The @code{init} method may take
arguments so as to pass values.
@subsection Factory Patterns
@emph{Nicola to complete}@*
(To be completed.)
@subsection Factory or Class Objects
Each class compilation sees the creation of a @b{factory object}
or @b{class object} that builds class-specific objects. Objects
instantiated by the factory object at run-time are @b{instances}
of the class. Class names begin with an uppercase letter, while
instance names begin with lowercase letter.
The compiler may create as many class objects as there are defined classes.
The class objects are conventional objects that may be dynamically typed,
receivers, and the recipients of class methods in superclasses.
@subsection NSClassFromString
Class names are about the only names with global visibility in Objective-C.
If a class is unknown at compilation but is available as a string at run time,
@code{NSClassFromString} may be used to return the class object:
@example
..
if ([anObject isKindOf: NSClassFromString(classTitle)] == YES)
..
@end example
The function returns nil if it is passed a string holding an invalid class name.
Class names, global variables and function exist in the same
name space, so classes and global variables may not share the same name.
@subsection respondsToSelector and NSStringFromClass
Run-time errors result when objects are stimulated to perform methods
absent from their repertoire. These errors are avoided by checking the
receiver's available methods, and if statically typed the compiler will
report them. Testing for this error may be left until run-time when the
message selector or the receiver's class varies.
The @code{respondsToSelector:} method inspects a receiver for compatibility
by sending them the method selector as an argument, and subsequently
returning a verification.
@example
if ([userObject respondsToSelector: @@selector(setOrigin::)] == YES)
@{
[userObject setOrigin: 2.0 : 2.0];
@}
else
@{
NSLog(@"%@ out of range", NSStringFromClass([userObject class]));
@}
@end example
@section Naming Conventions
@itemize @bullet
@item
Global variables may NOT share the same name as classes, because both
entities are allocated the same name space.
@item
Files with an .m extension hold Objective-C source code, while those with a
.h extension define protocols, or define classes and category interfaces.
@item
Implementation files have an @code{.m} extension.
@item
Interface files have a @code{.h} extension.
@item
Class, category and protocol names begin with an uppercase letter.
@item
Methods, instance variables, and variables holding instances begin
with a lowercase letter.
@item
A class may define methods using the same names as those held in other classes.
(See Overriding Methods.)
@item
A class may define instance variables using the same names as those
held in other classes.
@item
A class category may have the same name as another class category.
@item
An instance method and a class method may share the same name.
@item
A protocol may have the same name as a class, category, or any other entity.
@item
A method and an instance variable may share the same name.
@end itemize
@subsection Pitfalls of Using Class Names
@emph{Richard to complete}@*
(To be completed.)
@section The NSString Class
The NSString class defines objects holding character streams or @b{strings} using any spoken language. A
@b{static} instance of NSString is allocated at compile time. The creation of a static
instance of NSString is achieved using the @code{@@"..."} construct and a pointer:
@example
NSString *wasp = @@"Brainstorm";
@end example
@code{wasp} is a variable that refers to an NSString object representing
the ASCII string "Brainstorm".
@page

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,442 @@
@paragraphindent 0
@node Classes
@chapter Writing New Classes
@cindex writing new classes
@emph{Would you add Hands-on coding examples at the marked points, and perhaps any additional pertinent examples? Francis}@*
@section Interface
@cindex interface
A class interface declares instance variables, methods and
the superclass name, while the implementation file holds the
operational code that implements those methods. The interface
is included in the source using @code{#include}:
@example
#include "baseclass.h"
@end example
Typically the Interface and Implementation are held in separate files,
using the .h and .m extensions, respectively. They may, however,
be merged into one file, and a single file may implement many classes.
To ensure that a Header file is included only once, it is usual to
protect it with pre-compiler defines:
@example
#ifndef _MY_CLASS_H_INCLUDED
#define _MY_CLASS_H_INCLUDED
/* HEADER FILE */
#endif
@end example
This is the standard C technique to protect header files from
being included more than once.
@comment The role of the interface
@subsection Interface Capabilities
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.
@comment Writing an interface (syntax)
The syntax of a class interface is of the form:
@emph{I would like a better example interface than this? So would you create something more real?}@*
@example
// Need something here.
@end example
@itemize @bullet
@item
The interface is enclosed between the compiler directives
@code{@@interface} and @code{@@end}.
@item
@code{@@interface ThisClass : ThisClassSuperClass} 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.
@item
Braces enclose declared instance variables, each class' instance will
have all theses instance variables including instance variables
inherited from the superclass, and from the superclass of the
superclass, extending to the root class.
@item
Method declarations that begin with a "+" sign are class methods, and
are defined for the class object.
A class object inherits class methods from superclasses.
@item
Method declarations that begin with a "-" sign are instance methods,
and are defined for class instances. Class instances inherit instance
methods from superclasses.
@item
A method may share the name of an instance variable.
@item
A method return type is declared using the standard C syntax:
@example
- (float) scale;
@end example
which is a method returning a float.
@item
Argument types can be declared in the same way as method return types:
@example
- (void) setRadius: (float)aRadius;
@end example
which is a method that returns nothing, and takes a single float as
its argument.
Note. The default type for methods and messages (@code{id}) is assumed
when a return or argument type is not explicitly declared.
For example, @code{-name;} implicitly means a method returning @code{id}
(i.e. an object). It is usually better to avoid this and use
explicit typing as in
@example
- (NSString*) name;
@end example
@end itemize
@subsection Including Interfaces
Source modules (including Objective-C listings and interface files)
may integrate interfaces using @code{#include}. Thereafter the source
module may utilize the classes in those interfaces so as to:
@itemize @bullet
@item
Make instances of them.
@item
Send messages to invoke methods declared for them.
@item
Refer to instance variables in them.
@end itemize
With the exception of the root class, all working interfaces
integrate a superclass using either @code{#include} - 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:
@emph{ Here I have another example - would you replace it with something more meaningful?}
@example
#include "Superclass.h"
@@interface InterfaceName : InterfaceSuperclass
@{
// instance variables
@}
Declared methods
@end example
@subsection Referring to Classes - @@class
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.
If you are implementing a new class, you always need to include
the interface of the superclass using @code{#include};
@code{@@class} 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 @@class in this case, compilation will abort.
@b{Note. When you need to send methods to an object, it's better
to include the full class interface. Even in that case - it's
better *only* because it allows better type checking -
which is good of course - but not essential. And - to say it
all - if you use @@class that way, the compiler complains as soon
as you try to send a message to an object of a class declared
using @@class, so that you know you need to include the
interface for full type checking. This means it's a good idea
to always try with @@class if possible and only include the
interface if the compiler complains that it can't type-check
without the full interface.}
To inform the compiler that @b{Border} and @b{Square} are classes without including their full interface file, the following syntax is used:
@code{@@class Border, Square;}
Class names may also appear in interface files at times when
instance variables, return values and arguments are statically typed:
- (void) set
@emph{Another example of a class interface is required here, and perhaps an example of a class cluster would be useful as this is mentioned in chapter 1.}@*
a simple example of a class interface <fixme: what example ?>
@section Implementation
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.
In the C programming language C structures are singular entities
that encapsulate multiple data elements. The fields therein reside
in @b{name spaces} so they do not interfere with alike named
entities that are outside the structure. So the name spaces
define another partition.
Such C structures relate to C functions that provide the
application logic or defined mechanisms. Within a C structure
data elements may be local to a function, and are protected in
their name space.
@subsection Writing an Implementation
An implementation file contents are encapsulated between
@@implementation and @@end directives:
@example
#include "ClassTitle .h"
@@implementation ClassName :Superclass
@{
// instance variables
@}
// methods
@@end
@end example
The Implementation file uses @code{#include} to include a named
interface file holding all declarations. Thereafter, the
implementation need not declare instance variables, rather it
may be dedicated to defining methods that may include a number
of arguments; these are declared in the same way as the interface
file but without the semicolon:
@comment - Could you add something more meaningful here?
@example
@end example
@subsection Referring to Instance Variables
When an instance method of a certain object is called, the method can
refer to the object's instance variables directly by name.
The following example illustrates how a method definition refers to the
receiving object's @b{instance variable} called @code{line}.
@example
- (void) setLine: (BOOL)flag
@{
line = flag;
@}
@end example
You can access instance variables of other instances of the same class by using the operator @code{->}.
@emph{Example here.}
The following code fragment demonstrates how the GPRS class may declare a statically typed object as an instance variable called qosfive:
@example
@@interface GPRS :NSObject
@{
Connect *qosfive;
int frequency;
struct features *chargeband;
@}
@end example
Because qosfive is typed to the same class, the instance variables of the statically typed class are in the scope of the class. So the Connect method may set them directly:
@example
-makeAnotherQosfive
@{
if (!qosfive) @{
qosfive =[[Connect alloc ] init ];
qosfive->frequency =frequency;
qosfive->chargeband =chargeband;
@}
return qosfive;
@}
@end example
@b{Note. When the object is not a receiver, it is necessary that the object be @b{statically typed} in the class declaration.}
@c {the scope of instance variables (@@public, @@protected, @@private)}
@subsection Instance Variable Scope
In Objective-C instance variable have three types of @b{scope} or accessibility:
@itemize @bullet
@item
@code{@@private} restricts the instance variable to the declaring class, and not to inheriting classes.
@item
@code{@@protected} restricts the instance variable to the declaring class and inheriting
classes - this is the default scope.
@item
@code{@@public} globalises the instance variable, removing all the aforementioned restrictions.
@end itemize
@subsection Accessing Object Data Structures
The instance variables or data structures of objects are accessed by sending the object messages. An Objective-C object's instance variables may be changed to a @b{public} scope by converting them into a C structure.
The @code{@@defs(className)} directive produces a declaration list, where @code{public} is used as a pointer to the structure that approximates an instance of @code{Gprschannel}:
@example
struct gprschannelDef @{
@@defs(Gprschannel)
@}*public;
@end example
An object's instance variables may be given @b{public scope} through a @code{Gprschannel id} assigned to the pointer:
@example
id aGprschannel;
aWorker =[[Gprschannel alloc ] init ];
public =(struct gprschannelDef *)aGprschannel;
public->boss =nil;
@end example
@comment examples, with messages to self and super
@comment Messages to Self and Super
@subsection Super and Self
In the implementation of an Objective-C method, you may use the two reserved words @b{self} and @b{super}
@emph{example here}
.
In Objective-C some control over messaging is provided by @b{self} and @b{super}. @b{Self} searches for the
method implementation in the receiving object's class.
@b{Super} begins searching for the method implementation in the superclass of the class that defines the method with super.
A method implementation may refer to the target object as @b{self} or @b{super}, where
control is provided over which object performs the method.
To demonstrate the difference between @b{self} and @b{super} consider three classes:
@itemize @bullet
@item
One
@item
Two - One's superclass
@item
Three - Two's superclass
@end itemize
All three classes define a method called @b{traffic}, while Two defines a method called @b{Alert} that depends on @b{traffic}.
Sending a message to the One object to invoke the @b{Alert} method, causes the @b{Alert} method to send a @b{traffic} message to the same One object.
The following source code would search for the traffic method defined in One (or self's class).
@example
-Alert
@{
[self traffic ];
...
@}
@end example
When Twos source code calls this object super, the messaging routine will find the version of traffic defined in Three (the @b{superclass} of Two).
@example
-Alert
@{
[super traffic ];
...
@}
@end example
@b{Self} is a variable name that may be assigned new values particularly in definitions
of class methods that often focus on class instances as opposed to class objects. For example,
a method might combine allocation and initialization of an instance:
@example
+(id)newRect
@{
return [[self alloc ] init ];
@}
@end example
When in class methods self refers to class objects, and when in instance methods self
refers to instances. @b{self} and @b{super} focus on the receiver that is the object
being stimulated by a message.
@emph{Nicola/Richard add an example for self and super here - or two examples?}
implementation of the example class interface
@section Categories
A category may serve to replace a subclass; when adding methods to an existing declared class, and not to a new class, a @b{category name} is used.
An interface file may declare methods under a category name that is also used in the implementation file for the definitions of those methods.
Category methods are added to the class, and instances of the class will have the methods as part of their behaviour. As is the case with other methods, category methods are inherited by all the class' subclasses.
@subsection Adding to Classes
A category interface has the form:
@example
#include "ClassTitle .h"
@@interface ClassTitle (CategoryTitle )
declared methods
@@end
@end example
The category may include a interface, so as to allow its methods to access the instance variables of named classes.
A category implementation file has the form:
@example
#include "CategoryTitle .h"
@@implementation ClassTitle (CategoryTitle )
definitions of methods
@@end
@end example
Category methods may replace the conventional methods inherited by the class.
@b{Note. A category should not be considered a substitute for a subclass. }
@subsection Using Categories
Categories are useful for extending existing classes, so as to add new methods to frameworks. Categories are often used to separate the implementation of a new class into a number of source files. The obvious benefits of this program development strategy include: grouping subject-oriented methods; incremental compilation for large classes; help to logically divide the class when being created by a number of developers; and, permit configuration-specific classes targeting particular applications.
@page

Binary file not shown.

View file

@ -0,0 +1,33 @@
@c Foreword
@unnumbered Foreword
The aim of this document is to provide a GNUstep/Objective-C programming
manual (primarily tutorial in style) for the language, the GNUstep
base library, and the GNUstep makefiles package.
The manual does not cover installation instructions as these vary from
system to system, and are documented fairly well in the GNUstep HOWTO (http://www.gnustep.org).
What we want is a manual to tell programmers how to use the system,
particularly how to program with the base library in Objective-C,
but also to some extent from Java and Guile.
The target audience for this manual is the C, C++, or Java programmer
that wishes to learn to use Objective-C effectively. We assume that,
while the reader is able to understand English, it is quite possibly
not their native language.
For detailed class reference documentation the reader is directed to the GNUstep Base Library documentation (http://www.gnustep.org), and to the Apple Cocoa Objective-C Foundation documentation (http://www.apple.com).
Other reference documentation is -
@itemize @bullet
@item GNUstep-Java interface (documented as part of JIGS)
@item GNUstep-Guile interface (documented as part of gstep-guile)
@item Installation/configuration (documented in GNUstep HOWTO)
@end itemize

View file

@ -0,0 +1,60 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org" />
<title>
GNUstep Objective-C programming manual
</title>
</head>
<body background="/images/swirl.jpg">
<div align="center">
<img src="/images/newlogo.jpg" alt="Brainstorm logo" />
<p>
$Revision$ $Date$
</p>
</div>
<h1>
Brainstorm Objective-C programming manual
</h1>
<p>
The aim of this manual is to provide a tutorial and reference
manual to the use of the Objective-C language with the
GNUstep-base library. We want it to be readable enough for
programmers with a reasonable understanding of C or Java ...
even if english is not the programmers first/main language.
We also want it to cover the language in enough depth to
teach people how to get its full benefits, and understand its
use in the Brainstorm software environment.
</p>
<p>
The programing manual is a work in progress. At the time of
writing this, I believe that the overall structure is roughly
correct and the actual content of the document is perhaps one
third filled in. Once the content is complete, the document
will probably need a good bit of editorial work to make it
more readable and to check consistency etc.
</p>
<p>
The manual source is in texinfo format ... and is built
automatically to info, html, and postscript format.
</p>
<p>
</p>
<ul>
<li>
<a href="manual_toc.html">Read the HTML version online</a>
</li>
<li>
<a href="manual.ps">Download the PostScript version</a>
</li>
</ul>
<p>
Please send comments/criticisms/corrections to <a
href="mailto:richard@brainstorm.co.uk">richard@brainstorm.co.uk</a>
or <a
href="mailto:nicola@brainstorm.co.uk">nicola@brainstorm.co.uk</a>
</p>
</body>
</html>

View file

@ -0,0 +1,138 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename manual.info
@settitle Objective-C, Programming Manual
@c %**end of header
@ifinfo
@format
START-INFO-DIR-ENTRY
* GNUstepBase: Objective C Language and GNUstep Base Library
END-INFO-DIR-ENTRY
@end format
@end ifinfo
@ifinfo
Copyright @copyright{} 2001 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end ifinfo
@setchapternewpage odd
@titlepage
@title Objective-C Language
@title and GNUstep Base Library
@title Programming Manual
@author Francis Botto (Brainstorm)
@author Richard Frith-Macdonald (Brainstorm)
@author Nicola Pero (Brainstorm)
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 2001 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end titlepage
@contents
@iftex
@c Foreword
@include foreword.texi
@end iftex
@ifinfo
@c **Top node and master menu
@node Top
@top Objective-C Programming Manual
@include foreword.texi
@menu
* Introduction:: An introduction to object-oriented programming
* Objective-C:: An introduction to the Objective-C language
* Classes:: How to create a new class
* Objects:: Working with objects
* Distributed Objects:: Working with distributed objects
* Advanced Topics:: Topics that take you deeper into Objective-C
* Glossary:: Glossary of Terms
* Examples:: Examples of Objective-C code
* Make:: The GNUstep Make package
* Obj-C and Java:: Differences and similarities between Objective-C and Java
* Java and Guile:: Programming GNUstep in Java and Guile
@end menu
@c **end Top node and master menu
@end ifinfo
@page
@c Chapter 1, Introduction
@include Introduction.texi
@c Chapter 2, The Objective-C Language
@include ObjcLanguage.texi
@c Chapter 3, Writing New Classes
@include WritingNewClasses.texi
@c Chapter 4, Working with Objects
@include WorkingWithObjects.texi
@c Chapter 5, Distributed Objects
@include DistributedObjects.texi
@c Chapter 6, Advanced Topics
@include AdvancedTopics.texi
@c Appendix A: Glossary of Terms
@include Glossary.texi
@c Appendix B: Example Code
@include ExampleCode.texi
@c Appendix C: Using the GNUstep make package
@include GNUstepMake.texi
@c Appendix D: Comparison between Objective-C and Java
@include ObjcAndJava.texi
@c Appendix E: Programming GNUstep in Java and Guile
@include JavaAndGuile.texi
@unnumbered Concept Index
@printindex cp
@bye