In Ctalk, as in all object oriented languages, objects are the pieces of information that define and implement both code and data. Look at the following examples. They implement the same operations in BASIC, C, and Ctalk.
10 let a = 2 20 let b = a + a 30 print b int a, b; a = 2; b = a + a; printf ("%d\n", b); Integer new a; Integer new b; a = 2; b = a + a; stdoutStream writeStream b;
The examples look similar, but there is a difference in the object
oriented example. When a program declares new objects, in this case
a
and b
, Ctalk creates them as members of a
class. In this example, a
and b
are members of
the class Integer
.
If this were as far a object oriented programming went, these
statements would function exactly the same as their C counterpart,
int a, b;
However, classes belong to a library called a class
library. Class libraries contain all of the routines of
the language, and declarations of different types of
objects. A class library is organized so that the most
general classes are at the top of the hierarchy, and proceed
to more specialized subclasses. Each class may have
more than one subclass. Ctalk classes each have one
superclass, except for the class Object
, the
topmost class in the class hierarchy. More on class
hierarchies in a moment.
As the previous section mentioned, classes contain both the specification of objects and the source code of the routines or functions that operate with each class. These routines are called methods.
Look at this statement from the example above.
a = 2;
In this statement, the object a
is called the receiver
of the method. The method is the assignment operator, =
. The
number 2
is the argument to the method. When the
program tells a
to use the method =
, The =
character is not simply an operator, it is the name, or message
of a method that the language provides to the receiver, a
. In
simple examples, the operation is very similar to using a math
operator or function call. But the language treats the message as
separate from the operation it describes, which means the message is
extendable to any class that you might want to implement. We’ll
describe this in more detail in a moment.
Each class can have its own implementation of =
. The class
String
, for example, can have its own =
method, which
would do exactly what you’d expect.
String new myString; myString = "Hello, world!";
The next line from the example above,
b = a + a;
contains two methods, =
and +
. The receiver of =
is b
, and the receiver of +
is a
. The argument
of =
is the complete expression, a + a
.
Programs can do the same with character strings.
String new myString; myString = "Hello, " + "world!";
This is a simple example of a characteristic of computer languages:
polymorphism. That means different types of data have a common
interface and are treated the same by the language. When the =
and +
methods work with different classes of objects, we say
that the methods overload the operators.
In the next line from the example above,
stdoutStream writeStream b;
the receiver, stdoutStream
, receives the message writeStream
with the argument b
.
The receiver stdoutStream
is a class variable. There is
one stdoutStream
for its class, WriteFileStream.
stdoutStream
represents the program’s standard output. The
argument b
, however, is an instance of class
String
, and it contains an instance variable,
value,
which contains the character string itself. A
program can create as many instances of a class as it needs.
Each instance of a class contains its own data. For Integer
and String
objects, the data is simply the value
of the
object, either 2
or Hello, world!
Class WriteFileStream
objects, however, need to keep track of
more data than a basic type like an Integer
, data like the
permissions of the file stream, the position in the stream, the type
of I/O device, and the memory address of the stream itself. This
information is contained in instance variables. Each class
defines its own set of instance variables, and each instance of a
class has its own copy of them.
The methods that create objects, which are generally called new,
have a special status. They are called constructors. It’s
important to remember that they’re methods, not keywords or operators.
The following two statements look similar, but internally they function differently.
String new myString; WriteFileStream new myOutput;
Recall from the previous sections that the class hierarchy proceeds
from the more general objects at the top of the hierarchy, to the more
specific subclasses. Also, instances of class WriteFileStream
contain more instance data than many other classes of objects.
What actually occurs in the above statements is that
myString
is created like any other object, with its
own value
instance variable. myOutput
,
however, uses the new
method of its class, which first
creates the basic myOutput
object and then adds the
additional instance variables and data that we mentioned
above.
So in addition to the value
instance variable, which
the method new
obtains from the Object
class,
the object myOutput
also contains the instance
variables it needs to manage writing to a file. This is
called inheritance. We say that instances of class
WriteFileStream
inherit the value
instance
variable from the Object
class. Instances of class
WriteFileStream
also inherit other instance
variables, as described below.
Here is another example, which shows how classes inherit methods.
Suppose you wanted to create a class that represented positive
integers. You would accomplish this, most likely, by creating a
subclass of Integer.
Integer class PositiveInteger;
Objects of your new class could use the +
method of the
Integer
class. So you could write:
PositiveInteger new a; PositiveInteger new b; a = 2; b = a + 2;
Ctalk, if it doesn’t find a method for +
in the
PositiveInteger
class, then uses the +
method
of class Integer
.
If you wanted to subtract two PositiveInteger
objects, however,
you would need to implement the method -
to insure that the
result is also positive. The code within that method might look
something like the following.
if ((b = (a - a)) < 0) warning ("Negative result for PositiveInteger.");
The later chapters describe the details of creating your own classes and methods.
Let’s return to the constructor example above. You should
note that the WriteFileStream
class does not actually
define its instance variables.
WriteFileStream new myOutput;
This is because the instance variables necessary for reading from
files (with class ReadFileStream
objects) and writing to files
(with class WriteFileStream
objects) are similar. Instead,
Ctalk defines them in a superclass, FileStream
.
A section of the class hierarchy, showing the instance variables that each class defines, should help explain this organization.
Class Instance Variables Defined ----- -------------------------- Object <------ value Stream FileStream <------ streamMode <------ streamDev <------ streamRdev <------ streamSize <------ streamAtime <------ streamMtime <------ streamCtime <------ streamPos <------ streamErrno <------ streamPath ReadFileStream WriteFileStream
Ctalk does have a few keywords. Two of them are self and super. They’re mentioned here because they are essential to the creation of new objects, as well as other tasks.
Both self and super can occur only in methods.
The keyword self
refers to the receiver of the method
that self
occurs in. It’s functionally equivalent to
the keyword this
in C++.
The keyword super
refers to the superclass of the
method’s receiver. In some cases, it can also refer to the
receiver of an enclosing scope. This tutorial discusses the
uses of super
later on.
So when a new WriteFileStream
object gets its
instance variables from its class definition and the
definitions of each of its superclasses, its new
method can use super
to refer to a superclass’s
new
method. Very often, much of the initialization
has already been defined in the superclass methods, with
only a few tasks remaining to be done by the receiver class’s
constructor.
It might not be apparent from these simple examples, but the methods and instance data are closely tied together, and they’re independent of the methods and instance data of other classes. A simple operation might turn out to be more complex that it appears at first. But class inheritance helps separate and define more general tasks from the tasks that are specific to a single object.
Classes do not need to be completely separate, however. A method can reference some other class’s methods or object’s instance data if a program or method needs it.
The Ctalk Reference Manual describes the Ctalk class library, and the methods and variables, that each class defines.
Ctalk shares the strengths of the C programming language. Ctalk, like C, has very few keywords - nearly everything is an object or a method. The the rules for defining classes are very simple and general. You can write any code you like, no matter how system specific, and Ctalk can integrate the code into its class library.
As a historical note, Ctalk’s language syntax and class library organization are based very closely on the Smalltalk language, one of the earliest truly object oriented languages. You can find much information about Smalltalk and its design in on-line and printed documents.
But Ctalk is unique in that it lets you program in C when that is more suitable to a particular chore. The tutorial assumes that you’re fairly proficient in C. However, if you want to read further about the C language and object oriented programming, there are many books and tutorials, on line and in print, that describe these subjects in detail.