Objects

Classes and Prototypes

A "class" specifies the structure and behavior of a set of objects, known as its "instances". Each class has a special instance associated with it, known as its "prototype". Giving the name of the class in an expression specifies the class's prototype object.

This means that, although the terminology of "classes" and "instances" is used, Trylon 2 acts like a prototype-based system, in that there is no special class object for each class, and no distinction between "class" and "instance" functions, or "class" and "instance" fields. If you prefer to think in terms of "prototypes", then just think of the term "class" as a synonym for "clone family".

Functions, Fields, and Shared Fields

An object may have functions and fields. Fields defined in Trylon always have getter and setter functions defined; that is, they are "public".

There is also such a thing as a "shared field", whose value is shared by all instances of a class, much like a "static member variable" in C++, or a "class variable" in Smalltalk.

class MyClass
field my-field
 
my-shared-field = 'foo' # A shared field.
 
create: value
# Each instance has a separate value for "my-field".
my-field = value
 
bar
return my-shared-field + " " + value string
Classes Act As Namespaces

In Trylon, classes also can act as namespaces (a.k.a. packages). One class may be "contained" in another (as a shared field); functions in the child class have access to functions in the parent class.

class WindowSystem
class Event
create: raw-event
#...
 
class Window
next-event
# Notice that it knows the name "Event":
return Event new: get-raw-event

There is a top-level namespace called "Main", which acts as a global namespace for all Trylon objects. There is a namespace called "Standard" which contains some common classes. One of these is "Object", from which all prototypes descend. You can access the members of "Standard" without having to specify it explicitly.

Creating Objects

As in Smalltalk, one creates a new object by sending a message to a class. Or rather, to an instance of the class, usually the class's prototype. Consider this code for initializing an object:

class MyClass
fields c-name body
 
new: name
new-object = MyClass raw-new
new-object c-name = mangle-name: name
new-object body = List new
return new-object

It seems to be natural to write an initialization function that is called on the new object itself, instead of doing everything by operating on the object from the "outside". Such a function is much like a "constructor" in C++:

class MyClass
fields c-name body
 
create: name
c-name = mangle-name: name
body = List new
 
new: name
new-object = MyClass raw-new
new-object create: name
return new-object

But it's annoying and pointless to keep writing pairs of functions like this, especially since the "new" functions all look about the same. So in Trylon, anytime you define a function whose name begins with "create", the compiler will automatically generate the corresponding "new" function. Here are some examples of "create" functions:

class MyPoint
fields x y
 
create
x = 0
y = 0
 
create: x y: y
this x = x
this y = y
 
create-x: x y: y
this x = y
this y = 0
 
create-x: x
this x = x
this y = 0
 
test-point
point = MyPoint new
point = MyPoint new: 10 y: 20
point = MyPoint new-x: 10 y: 20
point = MyPoint new-x: 10