Smalltalk-80

A Mével, T Guéguen

► To cite this version:

A Mével, T Guéguen. Smalltalk-80. 1987, 10.1007/978-1-349-09653-4. hal-05188457

HAL Id: hal-05188457

https://hal.science/hal-05188457v1

Submitted on 26 Jul 2025

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
<figure><img src="image_2.png" /></figure>

# Smalltalk-80

A. Mével and
T. Guéguen
Macmillan Computer Science Series

Consulting Editor

Professor F.H. Sumner, University of Manchester

S.T. Allworth and R.N. Zobel, Introduction to Real-time Software Design, second edition

Ian O. Angell and Gareth Griffith, High-resolution Computer Graphics Using FORTRAN 77

Ian O. Angell and Gareth Griffith, High-resolution Computer Graphics Using Pascal

M.A. Azmoodeh, Abstract Data Types and Algorithms

C. Bamford and P. Curran, Data Structures, Files and Databases

Philip Barker, Author Languages for CAL

A.N. Barrett and A.L. Mackay, Spatial Structure and the Microcomputer

R.E. Berry and B.A.E. Meekings, A Book on C

G.M. Birtwistle, Discrete Event Modelling on Simula

T.B. Boffey, Graph Theory in Operations Research

Richard Bornat, Understanding and Writing Compilers

Linda E.M. Brackenbury, Design of VLSI Systems - A Practical Introduction

J.K. Buckle, Software Configuration Management

W.D. Burnham and A.R. Hall, Prolog Programming and Applications

J.C. Cluley, Interfacing to Microprocessors

J.C. Cluley, Introduction to Low Level Programming for Microprocessors

Robert Cole, Computer Communications, second edition

Derek Coleman, A Structured Programming Approach to Data

Andrew J.T. Colin, Fundamentals of Computer Science

Andrew J.T. Colin, Programming and Problem-solving in Algol 68

S.M. Deen, Fundamentals of Data Base Systems

S.M. Deen, Principles and Practice of Database Systems

Tim Denvir, Introduction to Discrete Mathematics for Software Engineering

P.M. Dew and K.R. James, Introduction to Numerical Computation in Pascal

M.R.M. Dunsmuir and G.J. Davies, Programming the UNIX System

K.C.E. Gee, Introduction to Local Area Computer Networks

J.B. Gosling, Design of Arithmetic Units for Digital Computers

Roger Hutty, Z80 Assembly Language Programming for Students

Roland N. Ibbett, The Architecture of High Performance Computers

Patrick Jaulent, The 68000 - Hardware and Software

J.M. King and J.P. Pardoe, Program Design Using JSP - A Practical Introduction
H. Kopetz, Software Reliability

E.V. Krishnamurthy, Introductory Theory of Computer Science

V.P. Lane, Security of Computer Based Information Systems

Graham Lee, From Hardware to Software - an introduction to computers

A.M. Lister, Fundamentals of Operating Systems, third edition

G.P. McKeown and V.J. Rayward-Smith, Mathematics for Computing

Brian Meek, Fortran, PL/1 and the Algols

A. Mével and T. Guéguen, Smalltalk-80

Barry Morrell and Peter Whittle, CP/M 80 Programmer's Guide

Derrick Morris, System Programming Based on the PDP11

Y. Nishinuma and R. Espesser, UNIX - First contact

Pim Oets, MS-DOS and PC-DOS - A Practical Guide

Christian Queinnec, LISP

Gordon Reece, Microcomputer Modelling by Finite Differences

W.P. Salman, O. Tisserand and B. Toulout, FORTH

L.E. Scales, Introduction to Non-linear Optimization

Peter S. Sell, Expert Systems - A Practical Introduction

Colin J. Theaker and Graham R. Brookes, A Practical Course on
Operating Systems

J-M. Trio, 8086-8088 Architecture and Programming

M.J. Usher, Information Theory for Information Technologists

Colin Walls, Programming Dedicated Microprocessors

B.S. Walker, Understanding Microprocessors

Peter J.L. Wallis, Portable Programming

I.R. Wilson and A.M. Addyman, A Practical Introduction to Pascal -
with BS6192, second edition

Non-series

Roy Anderson, Management, Information Systems and Computers

J.E. Bingham and G.W.P. Davies, A Handbook of Systems Analysis,
second edition

J.E. Bingham and G.W.P. Davies, Planning for Data Communications
Smalltalk-80

A. Mével and T. Guéguen

Edited by

Mario Wolczko,

Department of Computer Science,
University of Manchester

M
MACMILLAN
EDUCATION
© Editions Eyrolles 1987

Authorised English Language edition of Smalltalk-80, by A. Mével and
T. Guéguen, first published 1987 by Editions Eyrolles, 61 boulevard
Saint-Germain, 75005 Paris

Translated by M.J. Stewart

© English Language edition, Macmillan Education Ltd, 1987

All rights reserved. No reproduction, copy or transmission of this
publication may be made without written permission.

No paragraph of this publication may be reproduced, copied or
transmitted save with written permission or in accordance with the
provisions of the Copyright Act 1956 (as amended), or under the terms
of any licence permitting limited copying issued by the Copyright
Licensing Agency, London.

Any person who does any unauthorised act in relation to this
publication may be liable to criminal prosecution and civil claims for
damages.

First published 1987

Published by

MACMILLAN EDUCATION LTD

Houndmills, Basingstoke, Hampshire RG21 2XS
and London

Companies and representatives throughout the world

British Library Cataloguing in Publication Data

Mével, A.

Smalltalk-80. --- (Macmillan computer science series).

1. Smalltalk -80 (Computer system)

I. Title II. Guéguen, T.

005.13'3

QA76.8.S635

ISBN 978-0-333-44514-3

ISBN 978-1-349-09653-4 (eBook)

DOI 10.1007/978-1-349-09653-4
# Contents

<table><tr><td>Preface</td><td>xi</td></tr><tr><td>1 Introduction</td><td>1</td></tr><tr><td>1.1 Presentation</td><td>1</td></tr><tr><td>1.2 Smalltalk and its growth</td><td>1</td></tr><tr><td>2 Principles of the Language</td><td>6</td></tr><tr><td>2.1 Objects and messages</td><td>6</td></tr><tr><td>2.2 Classes and instances</td><td>7</td></tr><tr><td>2.3 Methods</td><td>8</td></tr><tr><td>3 Classes and Instances</td><td>9</td></tr><tr><td>3.1 Declaration of variables</td><td>9</td></tr><tr><td>3.1.1 Instance variables</td><td>9</td></tr><tr><td>3.1.2 Class variables</td><td>9</td></tr><tr><td>3.1.3 Global variables</td><td>10</td></tr><tr><td>3.1.4 Pool variables</td><td>10</td></tr><tr><td>3.2 Classes and subclasses</td><td>10</td></tr><tr><td>3.2.1 General remarks</td><td>10</td></tr><tr><td>3.2.2 Definition of a class</td><td>11</td></tr><tr><td>3.3 Metaclasses</td><td>11</td></tr><tr><td>4 Syntax</td><td>13</td></tr><tr><td>4.1 Literals</td><td>13</td></tr><tr><td>4.1.1 Numbers</td><td>13</td></tr><tr><td>4.1.2 Characters</td><td>14</td></tr><tr><td>4.1.3 Character strings</td><td>14</td></tr><tr><td>4.1.4 Symbols</td><td>14</td></tr><tr><td>4.1.5 Arrays</td><td>14</td></tr><tr><td>4.2 Variables</td><td>15</td></tr><tr><td>4.3 Messages</td><td>15</td></tr><tr><td>4.3.1 Composition of a message</td><td>15</td></tr><tr><td>4.3.2 Value returned by a message</td><td>16</td></tr><tr><td>4.3.3 Message priority</td><td>17</td></tr><tr><td>4.3.4 Cascaded messages</td><td>18</td></tr><tr><td>4.4 Blocks</td><td>18</td></tr><tr><td>4.4.1 Description of blocks</td><td>18</td></tr><tr><td>4.4.2 Blocks with arguments</td><td>18</td></tr><tr><td>4.4.3 Use of blocks in control structures</td><td>19</td></tr></table>
5 Methods 21

5.1 Messages and methods 21

5.1.1 Methods search 21

5.1.2 Object returned by a method 22

5.1.3 Temporary variables 22

5.2 Pseudo-variables 23

5.2.1 Pseudo-variable self 23

5.2.2 Super pseudo-variable 24

5.3 Primitive methods 25

6 Some Elements of the User Interface 26

6.1 General description 26

6.2 Main menu 27

6.3 Workspaces 27

6.4 Browsers 28

7 The Class Object 31

7.1 Identification of an object 31

7.2 Copies of objects 32

7.2.1 Non-duplicated instance variables 32

7.2.2 Duplicated instance variables 32

7.2.3 Copy message 33

7.3 Comparisons of objects 33

7.3.1 Equivalence of two objects 33

7.3.2 Equality of two objects 33

7.3.3 Comparison with nil 34

7.4 Indexed objects 34

7.5 Representation of objects 34

7.6 Control of errors 35

7.7 Control of messages 35

7.8 Dependencies between objects 36

7.9 Primitive messages 38

8 Description of Architecture of Classes 40

8.1 Class Behavior 41

8.1.1 Dictionary of methods 41

8.1.2 Instances 43

8.1.3 Manipulation of the class hierarchy 45

8.2 The classes ClassDescription and Class 47

8.2.1 Access to the description of a class 48

8.2.2 Category of classes and messages 48

8.2.3 Copy of messages 49

8.2.4 Compilation of methods 49

8.2.5 Access to variable names 50

8.2.6 Saving a class on a file 50

8.3 The class Metaclass 50

8.4 Multiple inheritance 50

9 The Magnitude Classes 53

9.1 The class Magnitude 53

9.2 The class Date 54
Contents

vii

9.2.1 Creation of instances

54

9.2.2 Information about the calendar

54

9.2.3 Arithmetic

55

9.2.4 Conversion

55

9.3 The class Time

56

9.3.1 Creation of instances

56

9.3.2 Information about the time

56

9.3.3 Conversions

56

9.3.4 Arithmetic

56

9.4 The class Character

57

9.4.1 Access to the instances

57

9.4.2 Testing the instances

57

10 The Numeric Classes

59

10.1 The class Number

59

10.1.1 Arithmetic

59

10.1.2 Mathematics

60

10.1.3 Tests

61

10.1.4 Truncation and rounding

62

10.1.5 Conversions

62

10.1.6 Nature of the object returned by arithmetic operations

63

10.2 The class Float

64

10.3 The class Fraction

64

10.4 The class Integer

64

10.4.1 Enumeration

64

10.4.2 Some additional arithmetic functions

65

10.4.3 Bit manipulation

65

10.4.4 Changing base

66

11 The Class Collection

67

11.1 Creation of instances

67

11.2 Manipulating the elements of a collection

68

11.2.1 Adding elements to a collection

68

11.2.2 Removing elements from a collection

68

11.3 Tests on a collection

69

11.4 Enumeration of a collection

69

11.5 Conversion of a collection

70

11.6 The subclasses of the class Collection

71

11.6.1 The class Bag

71

11.6.2 The class Set

71

11.6.3 The class Dictionary

71

11.6.4 The class IdentityDictionary

74

11.6.5 The class SequenceableCollection

74

The class OrderedCollection

77

The class SortedCollection

78

The class LinkedList

79

The class Interval

80

The class ArrayedCollection

81
<table><tbody><tr><td>12</td><td>The Class Stream</td><td>84</td></tr><tr><td>12.1</td><td>The class PositionableStream</td><td>85</td></tr><tr><td>12.1.1</td><td>The class ReadStream</td><td>87</td></tr><tr><td>12.1.2</td><td>The class WriteStream</td><td>87</td></tr><tr><td>12.1.3</td><td>The class ReadWriteStream</td><td>88</td></tr><tr><td>12.2</td><td>The class ExternalStream</td><td>88</td></tr><tr><td>12.2.1</td><td>The class FileStream</td><td>89</td></tr><tr><td>12.2.2</td><td>The class FileDirectory</td><td>89</td></tr><tr><td>13</td><td>Processes</td><td>91</td></tr><tr><td>13.1</td><td>The class Process</td><td>91</td></tr><tr><td>13.2</td><td>The class ProcessorScheduler</td><td>92</td></tr><tr><td>13.3</td><td>The class Delay</td><td>93</td></tr><tr><td>13.4</td><td>Semaphores</td><td>94</td></tr><tr><td>14</td><td>The Classes Point and Rectangle</td><td>96</td></tr><tr><td>14.1</td><td>The class Point</td><td>96</td></tr><tr><td>14.1.1</td><td>Creating a point</td><td>96</td></tr><tr><td>14.1.2</td><td>Messages supported by the class Point</td><td>96</td></tr><tr><td>14.2</td><td>Coordinate system within Smalltalk environment</td><td>98</td></tr><tr><td>14.3</td><td>The class Rectangle</td><td>99</td></tr><tr><td>14.3.1</td><td>Creating a rectangle</td><td>100</td></tr><tr><td>14.3.2</td><td>Instance methods</td><td>100</td></tr><tr><td>15</td><td>The Graphics Classes</td><td>105</td></tr><tr><td>15.1</td><td>The class Bitmap</td><td>105</td></tr><tr><td>15.2</td><td>The class DisplayObject</td><td>105</td></tr><tr><td>15.2.1</td><td>The class DisplayText</td><td>106</td></tr><tr><td>15.2.2</td><td>The class DisplayMedium</td><td>107</td></tr><tr><td>15.2.3</td><td>The class Form</td><td>110</td></tr><tr><td>15.2.4</td><td>The class Cursor</td><td>112</td></tr><tr><td>15.2.5</td><td>The class DisplayScreen</td><td>112</td></tr><tr><td>15.2.6</td><td>The class Path</td><td>113</td></tr><tr><td>15.3</td><td>The class BitBlt</td><td>114</td></tr><tr><td>15.4</td><td>The class Pen</td><td>115</td></tr><tr><td>16</td><td>Basic Elements of the Interface</td><td>118</td></tr><tr><td>16.1</td><td>Mouse</td><td>118</td></tr><tr><td>16.2</td><td>Windows</td><td>118</td></tr><tr><td>16.3</td><td>Pop-up menus</td><td>119</td></tr><tr><td>16.4</td><td>Standard windows</td><td>119</td></tr><tr><td>16.5</td><td>The system menu</td><td>120</td></tr><tr><td>17</td><td>Text Editing Windows</td><td>122</td></tr><tr><td>17.1</td><td>Scrollbars</td><td>122</td></tr><tr><td>17.2</td><td>How to select text</td><td>124</td></tr><tr><td>17.3</td><td>Edit commands</td><td>127</td></tr><tr><td>17.4</td><td>Workspaces</td><td>127</td></tr><tr><td>17.5</td><td>System workspace</td><td>128</td></tr></tbody></table>
Contents ix

18 Browsers 129

18.1 Description 129

18.2 The categories of class 130

18.3 The classes 131

18.4 Protocols 134

18.5 Methods 135

18.6 The code window 136

18.6.1 Editing a class 137

18.6.2 Editing a method 137

19 Other Windows 139

19.1 Inspectors 139

19.1.1 Description 139

19.1.2 Other inspectors 140

19.2 Debuggers 142

19.2.1 List of methods 143

19.2.2 The code window 143

19.2.3 Inspector of the receiver 144

19.2.4 Inspector of local variables 144

19.3 Views of external files 144

19.4 Graphics editors 147

19.4.1 The Form Editor 147

19.4.2 The Bit Editor 148

20 Management of User Events 150

20.1 The class InputState 150

20.2 The class InputSensor 150

21 Model-View-Controller System 152

21.1 The class View 152

21.1.1 The class WindowingTransformation 153

21.1.2 Instance variables of the class View 154

21.1.3 Messages understood by instances of View 156

21.2 The class Controller 158

21.2.1 Instance variables of Controller 158

21.2.2 Messages understood by instances of Controller 159

21.3 The class ControlManager 160

21.4 The class MouseMenuController 160

21.5 The classes StandardSystemView and StandardSystemController 162

21.6 Text-scrolling windows 163

21.6.1 Text-editing windows 164

21.6.2 Lists 165

21.7 Example 167

Index 175
# Preface

With the advent of affordable personal computing power, the Smalltalk-80 system is rapidly gaining in popularity. The Smalltalk-80 system can provide the personal computer user with a glimpse into the future of the programming process over the next decade.

This book is an introduction to programming in the Smalltalk-80 system. It describes the major elements of the system, namely the programming language, class structure and user interface, and serves as a concise reference for the most important classes in the system. Also included are many examples of Smalltalk-80 usage, and the source to a complete application. The description is based on the version 2 Virtual Image from Xerox, probably the most popular version of Smalltalk in use today.

The Smalltalk-80 system is large, and one cannot hope to describe it all in a book of this size. For a more comprehensive source, the reader is referred to Smalltalk-80: The language and its Implementation, by A. Goldberg and D. Robson, Addison-Wesley, 1983, and Smalltalk-80: The Interactive Programming Environment, by A. Goldberg, Addison-Wesley, 1984.
# 1 Introduction

## 1.1 Presentation

Smalltalk is one of several things: a programming language, an operating system, a programming environment, and a design and programming methodology. Many people consider Smalltalk to be a tool for knowledge representation, thus making it a serious competitor to Lisp and Prolog. It has moved on from its position as internal support system at the Xerox Palo Alto Research Center, which it held for ten years, to being used for the industrial production of software. The application areas in which it excels are application prototyping, interactive graphics systems and simulation. Although there are still some problems with speed of execution (mainly stemming from the interpretive nature of the system), spectacular results have been achieved in cost savings with certain types of software, especially in applications containing a high graphics or interactive component. The principal reason for this is that the Smalltalk environment takes the maximum advantage of the reuse of software components.

## 1.2 Smalltalk and its growth

Smalltalk is available on an increasing number of modern machines. It was first developed at Palo Alto in the beginning of the 1970s at the instigation of Alan Kay, and has evolved through three important stages:

- Smalltalk-72 was inspired by the Flex machine and the languages Lisp and Plasma

- Smalltalk-76 formalised the class, object and inheritance concepts inspired by Simula-67

- Smalltalk-80 is the latest version of the language, which was released from the Palo Alto laboratories.

Highlighted below are some of the stages in the design and development of Smalltalk at the PARC laboratories leading up to its general publication.

* October 1972 building of first Smalltalk interpreter

* December 1972 definition of Smalltalk-72 according to the following basic principles

- control with automatic de-allocation

- interaction by messages

- behaviour of objects defined by classes
1974 Smalltalk-74

- introduction of message dictionaries

- graphic control by BitBlt

1976 Smalltalk-76

- unification of classes and contexts as objects

- inheritance by class hierarchy

1978 Smalltalk-78

- portability achieved with NoteTaker

- improvement of performance

- experimental implementation on an 8-bit microcomputer (Z80 or 6502) TinyTalk

Summer 1979 first publications on Smalltalk produced.
Invitations to several companies to carry out experi-
mental implementations and participate in the evaluation
of the product: Apple, DEC, Tektronix, Hewlett Packard

August 1981 publication of an issue of 'Byte' devoted
to Smalltalk

September 1983 first Smalltalk licences granted by Xerox
Summer 1984 appearance of first implementations of
Smalltalk on different machines (Sun, SM90, etc)

Early 1985 Tektronix 4404 workstation made available

Spring 1985 'Methods' (a Smalltalk clone) available for
the IBM PC (DigiTalk Inc) and Smalltalk for the Apple
Lisa (Macintosh XL)

Autumn 1985 Smalltalk available on the Apple Macintosh
512K (Apple) and on the IBM PC/AT (SoftSmarts Inc). More
powerful Tektronix 4405 and 4406 models announced.

The essential characteristic of Smalltalk is its
economy of design. In fact, this is based on the four
concepts of object, message, class and inheritance.

Other mechanisms, such as the block or the dictionary
are seen by the programmer as constructs developed from
these basic concepts. This effort towards unification
can be pushed even further, but it currently has no
equivalent in other languages and systems. What it does
do is to facilitate rapid mastery of the programming
tools available.

From the outset of his research work, Alan Kay
established one of the principles that was later to be
followed in the different versions of Smalltalk. That
was the principle of reaction. At any time, an object is
active and must be capable of presenting itself to the
user in a tangible form. This property greatly facilit-
ates the creation and development of models.

One important difference between the architecture of
a traditional product and that of a product based on
Smalltalk is the absence of any frontier between the
application and the system, which is thus completely
open (this system is called the virtual image in Xerox
terminology). To take an example, in a traditional
approach, it is possible to find an application that implements a table control by hash coding while the compiler also uses the same algorithm. With Smalltalk, it would be a design error not to reuse something that is already present in the system.

Programming with Smalltalk is incremental by nature and therefore lends itself very well to the progressive development of models (by stepwise refinement). This has two important consequences:

- There is an intentional fusion of the roles of programmer and user, because the same metaphors are used. This means that the user of a program will be able to move progressively from simple utilisation to modification and extension of the program with the same type of interaction.

- Of course, it will become possible to mix intimately the different activities of programming and debugging.

It would be possible to expand on other characteristics of Smalltalk that improve programming efficiency. For example, one can cite the abandonment of the concept of mode (in the context of insertion mode, query mode, etc). One can also think of the principle of strong modularity which requires that no part of the system depends upon details of the internal functioning of other parts, this property being induced by the architecture of communicating objects. However, it is above all the importance of the graphics interface and its good integration with the system and the language that one associates with Smalltalk.

The graphics interface consists of a bit-mapped screen and a three-button mouse that permits zones of pixels to be designated on the screen. These devices allow

- working in an environment consisting of several windows

- mixing text and graphics

- maintaining a dialogue very easily, thanks to pop-up menus which disappear as soon as the button that calls them is released

- selecting points, areas and text, all with great ease.

It should be appreciated that the graphics screen and the mouse pointing device have nothing to do with 'add-ons' to an existing system. They are thoroughly integrated into the programming environment which exploits them to the full.

Many research projects are currently evaluating the value of Smalltalk-80 in industrial software production. It is still too soon to pass overall judgement on this product, but some characteristics can be underlined here and now.
The fashion for object oriented languages goes beyond the phenomenon of Smalltalk. A large number of tools that make explicit reference to the same concepts are available or currently appearing. Without striving to be exhaustive, the following can be mentioned: Formes (P. Cointe), Kool (P.Albert), Ulysses (Y. Autret), Mering (J. Ferber), Ceyx (J.M. Hullot), X-Lisp (D.Betz), R-Lisp (J.L. Roos), Ross (D. McArthur), Loops (Bobrow), Glisp (Novak), Act1 and Act2 (Liebermann and Theriault), Flavors (Cannon and Moon), LRO (Ch. Roche), C++ (B. Stroustrup), Objective-C (Cox and Love), Clascal (Apple), Methods (Digitalk Inc), Objective Pascal (N. Wirth and Apple), Oblogis (P.Y. Gloess), Neon (Kryia System Inc), Eiffel (B. Meyer), etc. All of these, mentioned at random, have quite diverse fields of application, but they all, to varying degrees, share certain aspects of Smalltalk. We can therefore say that the language conceived of by Alan Kay has had an important influence on the evolution of software production tools. The question is to establish whether this influence will be direct (effectively using Smalltalk), or indirect (borrowing ideas). Simula-67, which Smalltalk draws on considerably, has had a great influence on current programming languages, but its influence has been mainly indirect.

- The key to the question that has just been put on the future of the industrial use of Smalltalk depends very much on the choice that educational institutions make on the use of this language for their courses. The current availability of Smalltalk would indicate important growth potential from 1986 onwards. The present barrier to the wider industrial spread of Smalltalk is not the cost of the necessary workstations, but the lack of staff trained to use it.

- The extreme flexibility of Smalltalk allows the programmer to redefine the majority of his system functions with no restrictions. This can pose problems in a shared programming environment. Solutions exist, but are not yet integrated. However, for use in prototyping, this is not a serious handicap and the economies achieved promise increasing use of this tool.

There are currently numerous development projects based on Smalltalk. The most serious test of a widespread use of this product will be the existence of an exchange supply of software components written in Smalltalk.

The aim of this book is not to expound the theory of object languages but rather to offer a practical guide to programming in Smalltalk. There can be no question of developing here all the aspects of Smalltalk, because in its most recent versions it contains more than 230
classes and 4500 methods. Nevertheless, we have tried
not to neglect any of the important points of Smalltalk;
in particular, we have devoted several chapters to the
user interface and more precisely to the MVC (Model,
View, Controller) interface system that forms the basis
of every Smalltalk interface.
# 2 Principles of the Language

## 2.1 Objects and messages

All the entities used in Smalltalk-80 are objects. For example, an object can represent a number, a character, a drawing, a list, a program, an editor, etc.

An object has two main characteristics:

- it allows data belonging to it to be stored and accessed

- it can reply to a certain number of messages.

For example, the object 3.14 will respond to the message `sin` by returning the value 0, which is written:

3.14 sin

The only means of manipulating an object is to send it a message. Messages therefore constitute the interface between objects and the external world. The way in which an object responds to a message is private to it and does not have to be known externally.

Writing an application in Smalltalk consists of determining the objects necessary for the description of the problem and in defining the possible operations for each object.

For example, let us take a computer-aided drawing application. This must allow us to draw easily all simple geometric shapes. We will restrict ourselves to points, straight lines and circles. We can see already that just stating the problem indicates some of the objects that will have to be created; this produces a first breakdown of the problem into objects:

- drawing

- point

- line

- circle

Drawings will be defined by a list of points, a list of straight lines and a list of circles.

Points will be defined by two coordinates x and y.

Lines will be defined by two points.

Circles will be defined by a point and a radius.

The following operations are defined on drawings:

- display (displays the drawing on the screen)

- points (returns the list of points in the drawing)

- lines (returns the list of lines in the drawing)
- circles (returns the list of circles in the drawing)

- addPoint: aPoint (adds a point to the drawing)

- addLine: aLine (adds a line to the drawing)

- addCircle: aCircle (adds a circle to the drawing)

The following operations are defined on points:

- display (displays the point on the drawing)

- xy (returns the coordinates of the point)

- x: aNumber (initialises the x-coordinate of the point)

- y: aNumber (initialises the y-coordinate of the point)

The following operations are defined on lines:

- display (displays the line on the drawing)

- origin (returns the startPoint of the line)

- corner (returns the endpoint of the line)

- origin: aPoint (initialises the startPoint of the line)

- corner: aPoint (initialises the endpoint of the line)

The following operations are defined on circles:

- display (displays the circle on the drawing)

- centre (returns the centre point of the circle)

- radius (returns the radius of the circle)

- centre: aPoint (initialises the centre of the circle)

- radius: aNumber (initialises the radius of the circle).

This example demonstrates the modular aspect of Smalltalk. When the basic objects of an application and the operations on these objects are defined, the programmer can use them without knowing the detail of their construction; he can also reuse them in contexts that are quite different from those for which they were constructed.

## 2.2 Classes and instances

In the previous example, a drawing is made up of several points, several lines and several circles. All the points must interpret the messages sent to them in the same way.

This leads us to group together objects of the same kind into classes (that is, those objects that represent
the same sort of entity and interpret messages in the
same way).

Thus, the class of points whose elements will be
particular points is defined.

Objects contained in a class are called instances of
this class. The class describes the form in which in-
formation about its instances are stored; it also
describes the way in which its instances will reply to
the messages that they receive. In a class the instances
are represented by a certain number of variables called
instance variables. For the class of points the instance
variables are the coordinates x and y; for the class of
lines the instance variables are the origin and the cor-
ner.

2.3 Methods

The way in which an object responds to a message is
described in a method. All instances of a class use the
same method to respond to a message. Each class contains
a list of methods that allows its instances to respond
to the messages that are sent to them.
# 3 Classes and Instances

## 3.1 Declaration of variables

In the Smalltalk environment we encounter several types of variable that differ in their scope. These different types are:

- instance variables

- class variables

- global variables

- pool variables

### 3.1.1 Instance variables

Instance variables are variables that belong to an object and which allow it to be differentiated from other instances of its class. We can distinguish two types of instance variable, those that are indexed and those that are named.

#### Named instance variables

These are instance variables that are identified by a name. For the instances of the class *Point* there are two named instance variables, *x* and *y*.

When the name of an instance variable appears in an expression, this name refers to the value of the corresponding instance.

When a new instance is created, it contains instance variables specified by its class; the default value of these instance variables is the undefined object called `nil`.

#### Indexed instance variables

These are instance variables that are not accessed by name but by a numeric index. In contrast to objects that possess only named instance variables, those that possess indexed instance variables may have a varying number of instance variables.

In Smalltalk-80 there is for example a class with indexed instance variables which allows arrays to be represented; for each instance the number of variables corresponds to the size of the table.

### 3.1.2 Class variables

Class variables are variables that are shared by all the
instances of a class. For example, in the case of a computer-assisted drawing application, the outline of a circle is made up of several line segments; the number of these segments is the same for all circles, and one can therefore define it as a class variable.

### 3.1.3 Global variables

Global variables are variables that are shared by all objects. They are stored in a dictionary called Smalltalk. For example, all the classes are referenced by global variables whose name is the access key to the dictionary called Smalltalk.

### 3.1.4 Pool variables

Pool variables are variables that are accessible by the instances of several classes. In order to define a set of variables shared by several classes, it is necessary to define a dictionary that is common to these classes, this dictionary being itself a global variable.

## 3.2 Classes and subclasses

### 3.2.1 General remarks

Each object belongs to one and only one class, as can be represented thus:

<figure><img src="image_3.png" /></figure>

It can, however, be useful to share some elements of the description between several classes or to describe one class by means of another. (See also section 5.2.2.)

This is what happens in Smalltalk, where each class is described in terms of another class called its superclass. The instances of the new class are identical to those of its superclass, except for the additions
made explicit in the new class. The new class thus
defined is a subclass of its superclass.

One subclass is itself a class and can therefore also
have one or more subclasses. The set of classes thus
takes on a tree structure whose root is the class called
Object. Object is the only class that does not possess a
superclass.

The instances of each subclass inherit from all the
instance variables and from all the class variables, as
well as from all the methods of the superclass.

### 3.2.2 Definition of a class

To give a complete definition of a class, we need the
following elements:

- its name

- its superclass

- its new class variables

- its new pool variables

- its new instance variables

- the list of its new methods.

The name of the class is obligatory and must be
different from the name of any other existing class.

The superclass is obligatory and must correspond to a
class already in existence.

Variables are optional, but if they exist their name
must be different from any name already defined in the
set of its superclasses.

New methods may be added, or methods already defined
in the set of its superclasses may be redefined.

### 3.3 Metaclasses

As we have said earlier, each Smalltalk entity is an
object. Consequently, a class is itself an object. We
have also seen how each object belongs to one and only
one class. A class is therefore itself an instance of
another class that we call its metaclass. In earlier
versions of Smalltalk all the classes were instances of
one single metaclass. For reasons of flexibility (es-
pecially when creating new instances of a class), each
class is the sole instance of a metaclass.

The metaclasses are classes and therefore contain
methods that allow their instances (that is, the class-
es) to respond to the messages that they receive. As a
result, these methods will be called class methods,
while the other methods will be called instance methods.
When a class is created, a new metaclass is auto-
matically created. Among the messages sent to classes we
find for example the message new, which allows a new
instance of the class that received this message to be
created.
In contrast to other classes, metaclasses have no name; neither are they metaclass instances. They are all instances of the same class called **Metaclass**.

One can access the metaclass of a class by sending it the message class. So, if we call Point the class of points, we can access its metaclass with the expression:

## Point class

The metaclasses are classes and therefore have a superclass called **Class**.

To summarise, we can regard metaclasses in two ways:

- as instances of the class **Metaclass**,

- as a subclass of the class **Class**.

**Metaclass** and **Class** are two subclasses of the class **ClassDescription**.
# 4 Syntax

An expression is a sequence of characters which, when evaluated, always returns an object. In Smalltalk-80 there are four lexical types, as follows:

- literals that represent certain predefined objects like numbers, characters, character strings;

- variable names that represent variables that can be accessed in the context of the expression;

- messages;

- blocks that represent an expression whose evaluation is postponed.

## 4.1 Literals

### 4.1.1 Numbers

Numbers are objects that represent numerical values and respond to mathematical messages.

A number may be positive or negative; if it is negative it will be preceded by the minus sign -.

A number may be a decimal or an integer; if it is decimal it includes the decimal point in its sequence of figures, for example:

4
4.56
-7
-7.234
432

When the base used is not base 10, the number begins with its base expressed in base 10, followed by the character 'r' and ending with the expression of the number in that base. When the base is greater than 10, the first letters of the alphabet are used to represent numbers greater than 9, for example:

<table><thead><tr><td>Smalltalk expression</td><td>Base 10 equivalent</td></tr></thead><tbody><tr><td>2r10</td><td>2</td></tr><tr><td>2r1010</td><td>10</td></tr><tr><td>2r1.1</td><td>1.5</td></tr><tr><td>8r11</td><td>9</td></tr><tr><td>8r123</td><td>83</td></tr><tr><td>16rA1</td><td>161</td></tr><tr><td>16r-A1</td><td>-161</td></tr></tbody></table>
A number may be expressed in scientific notation; in this case the list of figures is followed by the character 'e' and the exponent is expressed in base 10. The number in front of the exponent is multiplied by the base to the power of the exponent, for example:

<table><thead><tr><th>Scientific notation</th><th>Base 10</th></tr></thead><tbody><tr><td>2.549e3</td><td>2459</td></tr><tr><td>-2.459e-3</td><td>-0.002459</td></tr><tr><td>2r10e3</td><td>16</td></tr><tr><td>2r10e-3</td><td>0.25</td></tr></tbody></table>

### 4.1.2 Characters

Characters represent the elements of the alphabet. They are indicated by the '$' followed by a character, for example:

$a
$A
$$
$9

### 4.1.3 Character strings

A string of characters represents a sequence of characters. This is indicated by placing the list of characters between quote marks. If the string itself contains an apostrophe, this must be doubled in order to avoid errors in interpretation, for example:

'this is a string'
'it's a string too'

### 4.1.4 Symbols

Symbols are strings of characters that are used to represent the names of objects in the system. They are written by prefixing them with the hash '#', for example:

#name1
#ThisIsASymbol

### 4.1.5 Arrays

An array is a structured object whose elements may be accessed by their numeric index. Each element of the array is a literal. It is indicated by the hash and the list of its elements is enclosed by brackets. If an array or a symbol is included among the elements of the array, there is no need for a hash in front of these elements, for example:

#(1)
#(2 7 9)
#(1 'one' one (1 one 'one is a string'))
## 4.2 Variables

A variable allows an object to be referenced; all variables except indexed variables have a name. A variable name may be used in an expression to designate an object. From a given object one may access objects referenced by variables whose name is known by this object.

Because the range of instance variables of an object is limited to the object itself, they will be inaccessible from any other object, and can therefore only be used by methods defined for this object.

A variable name is a sequence of alphanumeric characters and must begin with a letter, for example:

v1
nameOfVariable
NameOfVariable

By convention, variables whose range is limited to the object (instance variables and temporary variables) begin with a lower case letter, and variables that are accessible by several objects (global variables, pool variables, class variables) begin with an upper case letter.

To assign a value to a variable, the special character ' `<-` ' is used, preceded by the variable name followed by an expression whose evaluation will return an object that will then be referenced by the variable, for example:

variable1 <- 1
variable2 <- 'variable 2 references a string of characters'
variable3 <- Point class
variable4 <- variable5 <- 123

## 4.3 Messages

Messages allow interactions between objects, for example:

2 sqrt
returns the square root of 2,
2 + 8
returns the sum of 2 and 8,
variable1 + 4
returns the sum of 4 and the number referenced by variable 1,
variable1 > variable4
compares the objects referenced by the two variables,
10 raisedTo: 2
returns 10 raised to the power of 2.

### 4.3.1 Composition of a message

An expression requires a receiver to appear, followed by
a selector and possibly arguments. The receiver and the arguments are described by expressions, while the selector is described by a literal, for example:

2 sqrt

the receiver is 2, the selector is sqrt,

2 + 8

the receiver is 2, the selector is +, the argument is 8,

variable1 + 4

the receiver is the object referenced by variable1, the selector is +, the argument is 4,

variable1 > variable4

the receiver is the object referenced by variable1, the selector is >, the argument is the object referenced by variable4,

10 raisedTo: 2

the receiver is 10, the selector is raisedTo:, the argument is 2.

There are three types of messages, characterised by the number of arguments:

### Unary messages

These are messages that have no argument, for example:

2 sqrt

### Keyword messages

This is the most common form of message. The selector is made up of one or more keywords preceding each argument.

Each keyword terminates with `':'`, for example:

10 raisedTo: 2

the selector is raisedTo:, the unique keyword is raised-To:, the argument is 2,

list at:2 put: 1

the selector is at:put:. the keywords are at: and put:; the arguments are 2 and 1.

### Binary messages

In the case of a single argument, it is possible not to use a keyword for the selector but to replace it with a selector made up of one or two non-alphanumeric characters; in this case the message is said to be binary, for example:

2 + 8

variable1 >= variable4

### 4.3.2 Value returned by a message

In response to the message the receiver returns an object which becomes the value of the expression. In the following example

2 + 3 * 4
the first message sent to object 2 has as its selector +, and as its argument 3; the object returned in response to this message is object 5. The expression then becomes

`5 * 4`

and the result returned by the first expression is the object 20.

In the case where the expression includes an assignment, the object returned is the object referenced by the assignment variable. For example, the expression

`variablel <- 2 + 3 * 4`

returns the object 20.

### 4.3.3 Message priority

Messages are taken in order from the left of the expression, with the following priorities (in decreasing order of precedence):

- unary message

- binary message

- keywords message

In the example

`10 raisedTo: 2 + 3 sqrt`

the highest priority message is the unary message `sqrt`; the value returned will be 1.73205. The second message will be the binary message `+`, the returned value being 3.73205. The last message will be the keyword message `raisedTo:`, with the value returned being 10 raised to the power of 3.73205, that is $5395.74$.

In order to alter the order in which messages are sent, parentheses may be used. The highest priority message is the one enclosed between parentheses. For example, in the expression

`2 + (3 * 4)`

the first message sent will be `*`, which will go to the object 3 with argument 4; the result will be 12, which will become the argument for the selector `+` of the second message. The final object returned will thus be 14.

When several keywords appear in a message, they are grouped under a single selector. For example, in the expression

`10 raisedTo: 2 raisedTo: 3`

the selector will be `raisedTo: raisedTo:`, which is not a correct selector. Parentheses must therefore be used, as follows:

`(10 raisedTo: 2) raisedTo: 3`

or

`10 raisedTo: (2 raisedTo: 3)`
#### 4.3.4 Cascaded messages

It is possible to send several messages to the same object by separating these messages with semi-colons. In the following example

```
list at: 1 put: 'one'
```

```
list at: 2 put: 'two'
```

```
list at: 3 put: 'three'
```

could be written

```
list at: 1 put: 'one'; at: 2 put: 'two'; at: 3 put: 'three'
```

The use of cascaded messages is not obligatory but it does make the writing of expressions more concise.

### 4.4 Blocks

#### 4.4.1 Description of blocks

Blocks are Smalltalk objects used in control structures. A block is a sequence of expressions separated by full stops; it begins with the character `'['` and ends with the character `']'`. Evaluation of a block must be requested explicitly; this allows it to be used in control structures. An example of a block is:

```
[variable1 <- 1. variable2 <- 2]
```

If there is a point between the last expression and the final bracket, it will be ignored.

A block is an object that can execute expressions placed within brackets if it receives the message value. For example

```
[variable1 <- 1. variable2 <- 2] value
and
```

```
variable1 <- 1. variable2 <- 2
will produce the same result.
```

Evaluation of a block returns the value returned by the last expression in the block. When a block contains no expression the value returned is `nil`.

#### 4.4.2 Blocks with arguments

It is possible to pass one or more arguments to a block before its execution. In a block the arguments are specified at the beginning of the block by identifiers beginning with the colon `:`. Arguments are separated from expressions by the bar character `|`.

For example, the block

```
[:i | variable1 <- i]
```

is a block with an argument that is `i`. The block

```
[:i :j | variable1 <- i. variable2 <- j]
```

is a block with two arguments, `i` and `j`.

The arguments of a block are variables local to that block.
To evaluate a block with an argument, you must send it the message value: with an argument that will be passed to the block. In the event of two arguments, the message to be used is value:value:.

Use value: value: value: and value:value:value:value: for three or four arguments; use valueWithArgs: anArray for more.

### 4.4.3 Use of blocks in control structures

When we refer to classic programming languages like Pascal or C, we find that they contain three types of control structure: the loop (for, do), the test (if then else) and the conditional loop (while, until). These structures are also found in Smalltalk-80 and make use of blocks. Smalltalk-80 does not have an equivalent to the multi-branch (case) statement.

#### Loops

Starting with a list of elements it is possible to execute a block for each element in the list, with each element becoming the argument of the block. This is done by sending the message do: to a list of elements. For example

```ruby
listIntegers do: [:eachInteger | sum <- sum +
    eachInteger]
```

will have the effect of calculating the sum of all the integers contained in the list.

#### Tests

Boolean objects are returned from messages like >, <, >=, <= etc. These Boolean objects, true and false, respond to the messages ifTrue:, ifFalse:, ifTrue:ifFalse: and ifFalse:ifTrue:. The arguments of these messages are blocks that will be evaluated or not, depending on whether the receiver is true or false. In the example

```ruby
anInteger < 0 ifTrue: [anInteger <- 0 - anInteger]
```

the sign of anInteger is changed if it is negative.

In the example

```ruby
anInteger < 0 ifTrue: [anInteger <- 0] ifFalse:
    [anInteger <- anInteger sqrt]
```

anInteger is set to 0 if it is negative, otherwise its square root is assigned to it. To clarify the expression, it can be formatted differently and may for example be written as follows:

```ruby
anInteger < 0 ifTrue: [anInteger <- 0]
    ifFalse: [anInteger <- anInteger sqrt]
```

#### Conditional loops

A conditional loop operates for as long as a condition is true or holds. This condition is evaluated at each
iteration of the loop. That can for example be achieved
by sending the message whileTrue: or the message while-
False: to a block with another block as argument. The
example below allows the factorial of a number to be
calculated iteratively

fact <- 1.
[aNumber > 1] whileTrue:
[fact <- fact * aNumber.aNumber <- aNumber - 1]

So long as aNumber is greater than 1, the value
returned by the evaluation of the first block is true
and therefore the second block is evaluated. As soon as
aNumber is equal to 1, the evaluation of the first block
returns false and the iteration stops. The result will
be referenced by the variable fact. This example can be
handled with the message whileFalse:

fact <- 1.
[aNumber <= 1] whileFalse:
[fact <- fact * aNumber.aNumber <- aNumber - 1]

Note that these control structures are constructed
from the basic language features, namely, blocks methods
and messages, and require no extra features in the
language.

For example, the ifTrue: ifFalse: control structure
is built from two methods, one in class True (whose sole
instance is true),

ifTrue: aBlock ifFalse aSecondBlock

↑aBlock value

and another in class False (whose sole instance is
false),

ifTrue: aBlock ifFalse: aSecondBlock

↑aSecondBlock value
# 5 Methods

## 5.1 Messages and methods

A method describes how an object is going to reply to a message. The name of a method is the same as the name of the message to which the method must allow a response to be made. A method consists of its name followed by a list of expressions separated by full stops. For example, the method of the class Point which returns the x-coordinate of that point will be written

<table><tr><td>x</td><td>message name</td></tr><tr><td>↑x</td><td>return of instance variable x</td></tr></table>

The method of class Point which alters the x-coordinate of the point will be written

<table><tr><td>x: aValue</td><td>message name</td></tr><tr><td>x <- aValue</td><td>assigns to x the value aValue</td></tr></table>

The method of class Point which displays the point on the drawing will be written

<table><tr><td>display</td><td>message name</td></tr><tr><td>|square|</td><td>definition of a variable</td></tr><tr><td>square <- Form new.</td><td>local to method</td></tr><tr><td>square extent: 2@2</td><td>square becomes a new instance of Form</td></tr><tr><td>square black.</td><td>size of square is fixed as 2 x 2 pixels</td></tr><tr><td>square displayAt: x@y</td><td>square is black</td></tr><tr><td></td><td>display square at position (x,y)</td></tr></table>

Form is a predefined Smalltalk class.

new is a method of class which creates a new instance.

extent:, black and displayAt: are three instance methods of the class Form.

The arguments found in the method name are variables local to the method and cannot be altered. For example

<table><tr><td>x:aValue</td><td>aValue <- aValue + 1.</td></tr><tr><td>x <- aValue</td><td>produces a syntax error.</td></tr></table>

### 5.1.1 Methods search

When an object receives a message, it looks in its class
for a method having the same selector as the message received. If it does not find it, it continues its search in the superclass of its class; this search is continued through the sequence of its superclasses until the correct method is found.

If on reaching the root class, `Object`, the method has not been found, there is an error. The receiver is then sent the message `doesNotUnderstand:`, whose argument is the message whose selector has not been found.

The method which replies to the message `doesNotUnderstand:` is set up in the class `Object` and is therefore known to all objects. It indicates to the programmer that there is an error.

If the search is successful, each expression of the method found is evaluated. When all expressions have been evaluated, the receiver returns to the sender an object which is the response to the message received.

### 5.1.2 Object returned by a method

When a method terminates the receiver returns an object to the sender. The default object is the receiver itself. When it is required to return another object, this is indicated in the method by prefixing the object to be returned with the character `↑`.

As soon as this character is found, the object produced by the expression that follows is returned to the sender and the method terminates. For example, the following method of class `Point`

**xPositive**

`x > 0 ifTrue: [↑true] ifFalse: [↑false]`

will return true if the x-coordinate of the point is positive, and false otherwise. This method may be written more simply as

**xPositive**

`↑x > 0`

### 5.1.3 Temporary variables

As we saw in the example dealing with the display method in class `Point`, a variable, square, was introduced. Temporary variables like this may be declared in a method, but they are accessible only during execution of the method.

To declare temporary variables their name must be placed between two `|` characters.

Declaration of these variables must occur between the method name and the list of expressions. Every time that a method is executed these variables are set to `nil`. For
example, the method

### invertXandY

```
|temporaryVariable|
temporaryVariable <- x.
x <- y
y <- temporaryVariable
```

allows the coordinates of a point to be inverted using the temporary variable called `temporaryVariable`.

## 5.2 Pseudo-variables

A pseudo-variable is a variable whose value cannot be altered by assignment.

Some pseudo-variables are constants; that is, they always refer to the same object. So far we have met three, namely

- `nil` the default value of a variable

- `true` the object returned by a true condition

- `false` the object returned by an false condition.

Other pseudo-variables depend on the context in which they are used. Such is the case with the pseudo-variables, `self` and `super`.

### 5.2.1 Pseudo-variable self

The pseudo-variable `self` always refers to the receiver of the message itself. Every method has access to the self pseudo-variable. For example, the method

#### abs

`self < 0 ifTrue: [↑0 - self]`

returns the absolute value of the receiver.

`self` also allows recursion to be handled, as in the following example:

#### factorial

`self = 0 ifTrue: [↑1].`

`↑self*(self - 1) factorial`

When the expression `3 factorial` is evaluated, `self` will represent 3 at the first pass. The method will request the response to the message (`self - 1`) factorial, namely 2 factorial, and so on until 0 factorial. This may be shown diagrammatically as follows:

<table><tr><td>3 factorial</td><td>self = 3</td></tr><tr><td>2 factorial</td><td>self = 2</td></tr><tr><td>1 factorial</td><td>self = 1</td></tr><tr><td>0 factorial</td><td>self = 0</td></tr><tr><td>↑ 1</td><td></td></tr><tr><td>↑ 2</td><td></td></tr><tr><td>↑ 6</td><td></td></tr></table>

When a message is sent to `self`, the search for the method corresponding to the message will begin in the
class of the object referenced by self. This class may
well be a subclass of the class containing the first
method. This is a consequence of the strategy used to
look for a method.

5.2.2 Super pseudo-variable

There is a second pseudo-variable, called super, that is
also accessible by all methods.

This pseudo-variable again refers to the receiver,
but its strategy for searching for a method is differ-
ent.

When a message is sent to super, the method search
begins not in the receiver's class, but in the super-
class of the class that the message was sent from.

For example, say we have a hierarchy of three
classes, as shown in the following figure:

<figure><img src="image_4.png" /></figure>

in which a b c are three respective instances of classes
A B C. Say that in class A the method is

name

↑'A'

in class B the method is

name

↑'B'

and in class C the method is

name

↑'C'

Say that in class B the methods are

myName

↑self name

and

superName

↑super name
The different results of the messages myName and superName sent to objects b and c will be

<table><thead><tr><td>Expression</td><td>Result</td></tr></thead><tbody><tr><td>c myName</td><td>'C'</td></tr><tr><td>c superName</td><td>'A'</td></tr><tr><td>b myName</td><td>'B'</td></tr><tr><td>b superName</td><td>'A'</td></tr></tbody></table>

One of the most frequent cases of the use of the super pseudo-variable is when redefining a method in a subclass. For example:

**initialise**

super initialise.

self init

This method calls the method with the same name that is located in a superclass of the class in which it is embedded.

### 5.3 Primitive methods

We have just seen that in order to respond to a message an object executes a method; execution of this method results in the evaluation of one or more expressions and therefore also to the sending of messages to other objects. To avoid an infinite regress of message sending, there must be methods that do not send any messages, but perform basic operations. These methods are not embedded in the virtual image but in the virtual machine; they are written in machine code and are referred to as primitive methods. For example, the mathematical operations + * / - are primitive methods.

There are about a hundred primitive methods; the number varies according to the implementation.

When a method is a primitive method, it begins with an expression of the form

`<primitive #n>`

where n is the number of the primitive.

If the primitive cannot be executed correctly, the expressions that follow it in the method are executed; this allows errors to be controlled.
# 6 Some Elements of the User Interface

Part of this book is devoted to the user interface in Smalltalk. However, at this point we want to give the reader some elements so that he or she may test the examples that have already been presented and those that are to follow in the book. It is worth repeating once again that learning Smalltalk is best done in a practical context; this means that the support of a machine, while not absolutely necessary, is highly desirable for tackling the remainder of this book.

<figure><img src="image_5.png" /></figure>

## 6.1 General description

When compared with a traditional machine, the Smalltalk interface has three special features:

- a bitmap screen

- a three-button mouse

- multiple windows and pop-up menus.
A window is an area of the screen corresponding to the user interface of a particular application.

A pop-up menu is a menu that appears on the screen when the user presses one of the mouse buttons and which disappears when the button is released to execute the selected function.

## 6.2 Main menu

Depending on the window types, the pop-up menus vary. When the cursor is outside any window, the user can make the menu shown below appear by pressing the middle button of the mouse.

<figure><img src="image_6.png" /></figure>

We shall briefly describe the main functions of this menu.

restore display

redisplays the complete screen,

file list

opens a window accessing the file system,

browser

opens a window viewing the classes and methods,

workspace

opens a window in which expressions can be evaluated,

save

saves the virtual image in a file,

quit

exits the Smalltalk system.

## 6.3 Workspaces

A workspace is a window in which it is possible to edit text and evaluate expressions.

In this type of window the left-hand button of the mouse is used to designate a position in the text or select a part of this text, showing it in inverse video.

The middle button on the mouse is used to edit the text or evaluate expressions.
<figure><img src="image_7.png" /></figure>

The main functions of the middle button menu are:

again

which repeats the last text replacement,

undo

cancels the last editing function,

copy

copies the selected text into a buffer memory,

cut

removes the selected portion of text, placing a copy in
the buffer memory

paste

inserts the text held in the buffer at the position
marked by the cursor or replaces the selected section of
text with the contents of the buffer,

do it

evaluates the selected portion of text,

print it

evaluates the selected portion of text and displays the
result of the evaluation.

6.4 Browsers

Browsers are windows used to browse through the classes
and methods in the system.

For greater clarity of presentation, classes and
methods are grouped into categories. These categories
are arbitrary and have no effect on the system archi-
tecture.

A browser type window contains five sub-windows. The
four at the top are windows that can access lists; the
one at the bottom is a text editing window. The four top
windows contain respectively:

- the class categories - classes belonging to the same
category are classes which deal with similar problems

- classes

- the methods (or protocols) categories, methods that
<figure><img src="image_8.png" /></figure>

have a close functionality are grouped into the same category
- methods.

The bottom window serves mainly for editing classes and methods. When a class is selected and no method category is chosen, the bottom window contains the definition of the class. The figure below shows a browser containing the definition of the class Point.

<figure><img src="image_9.png" /></figure>
Having edited the definition of an existing class, it is possible to alter the characteristics of this class or create a new class. In order to save these characteristics, you need to use the **accept** function of the middle button mouse menu.

When a protocol is chosen, the user can create a new method or alter an existing method in the bottom window. To link the method into the system the accept function must again be used; this has the effect of compiling the text of the method. The figure below shows a browser viewing the text of the method <= in class Point.

<figure><img src="image_10.png" /></figure>

The two types of windows that we have just described are sufficient for testing most of the examples in this book. The other principal types of windows are:

- Debuggers - for examining the state of computation during the evaluation of an expression

- FileLists - which allow access to the external files

- Transcripts - there is generally one single window of this type in which the system displays information relating to the progress of the Smalltalk session.
# 7 The Class Object

The class Object is the superclass of all other classes and consequently the methods that are defined in it are accessible by all Smalltalk-80 objects. Of course, these methods can be redefined in any class.

## 7.1 Identification of an object

The characteristics of an object depend on the class to which it belongs. Certain messages allow access to these characteristics. We have already met one of these:

class

which when sent to an object returns the class of that object.

For example,

2 class

returns `SmallInteger`,

$A$ class

returns `Character`.

There are others:

`isKindOf: aClass`

allows one to find out if the receiver is an instance of the argument aClass or of one of its subclasses.

For example,

2 isKindOf: SmallInteger

returns true,

2 isKindOf: Number

returns true, because SmallInteger is a subclass of `Number`.

`isMemberOf: aClass`

allows one to find out if the receiver is a direct instance of aClass.

For example,

2 isMemberOf: SmallInteger

returns true,

2 isMemberOf: Number

returns false.

`respondsTo: aSelector`

allows one to find out if the receiver understands the message. For example,

2 respondsTo: #+

returns true,

2 respondsTo: #at:

returns false.

The selectors of messages are instances of class `Symbols` and are therefore prefixed with the hash.
## 7.2 Copies of objects

It is possible to copy an object, that is, create a new object having the same characteristics as the original.

There are two ways of making a copy, depending on whether the instance variables of the object are duplicated or not.

### 7.2.1 Non-duplicated instance variables

Instance variables are shared between the original and its copy, as in the following diagram.

<figure><img src="image_11.png" /></figure>

If the original or its copy alters one of its instance variables, this alteration is also made for the other object. The message to make this copy is

shallowCopy

For example,

a <- 'ABC'

b <- a shallowCopy

assigns a copy of a to b.

### 7.2.2 Duplicated instance variables

Instance variables belong to the copy; there is no longer any dependence between the original and its copy. We have the following arrangement:

<figure><img src="image_12.png" /></figure>

The copy is made in a recursive way at the level of the instance variables; that is, the objects referenced by the instance variables can themselves have their own instance variables. These instance variables are also duplicated up to the point of having objects without instance variables.
The message to make this copy is
`deepCopy`

For example, if `f1` is an instance of class `Form` (that is, a bitmap - see 15.2.3), then after evaluating the following expressions (the reverse message changes black to white and vice versa):

`f2 <- f1 deepCopy.`

`f3 <- f1 shallowCopy.`

`f1 reverse`

`f2` will contain a copy of the original bitmap, whereas `f1` and `f3` will both refer to the original bitmap, which has been reversed.

### 7.2.3 Copy message

The class `Object` contains the definition of the method that will respond to the message `copy`

This method calls `shallowCopy` directly. In the subclasses of `Object` it is possible to redefine this method according to the nature of the objects to be copied.

Some variables can thus be duplicated while others cannot.

## 7.3 Comparisons of objects

Two types of comparisons may be made. The equivalence and the equality of two objects can be tested.

### 7.3.1 Equivalence of two objects

Two expressions are equivalent if they refer to the same object. The message for testing equivalence is
`==anObject`

For example:
`variable1 <- anObject.`
`variable2 <- anObject.`
`variable1==variable2`

returns true, because variable 1 and variable 2 refer to the same object. We can also test if two objects are not equivalent with the message
`~~anObject`

### 7.3.2 Equality of two objects

Whereas equivalence is defined in class `Object`, and should not be redefined, equality should be defined appropriately for each class.

For example, two instances of class `Point` are considered to be equal if their `x-` and `y-values` are equal, but are not equivalent unless they are the same object:

`variable1 <- 3@4`

`variable2 <- 3@4`

`variable1 = variable2` returns true

but `variable1==variable2` returns false.
### 7.3.3 Comparison with nil

There are two messages to compare an object with the `nil` object. The message

`isNil`

returns true if the receiver is `nil`. The message

`notNil`

returns true if the receiver is not `nil`.

## 7.4 Indexed objects

We have seen how an object can have named instance variables and/or indexed instance variables. For objects with indexed instance variables, there are several messages that allow access to the objects referenced by these variables. These are

`at: anIndex`

which returns the object referenced by the instance variable that has the index `anIndex`.

`at: anIndex put: anObject`

allows the object `anObject` to be assigned to the instance variable of index `anIndex`.

`basicAt: AnIndex`

is equivalent to `at:`, but must not be redefined in the subclasses of `Object`.

`basicAt: anIndex put: anObject`

is equivalent to `at:put:`, but must not be redefined in the subclasses of `Object`.

`size`

returns the number of indexed instance variables in the receiver.

`basicSize`

is equivalent to `size`, but must not be redefined in the subclasses of `Object`.

For example,

`8 size`

returns 0

`'ABC' size`

returns 3

`#(1 2 3 (2 4)) size`

returns 4

`#(1 2 3 (2 4)) at: 4) size`

returns 2

## 7.5 Representation of objects

Smalltalk-80 represents objects internally in a binary form which is not readable by users. Therefore, it also provides methods to generate representations of objects in a human-readable form. There are two possible forms of external representation:

- a first external representation in summary form,

- a second representation which is an expression that, if evaluated, will recreate the object.

There are two methods in class `Object` that create such representations. These are

`printString`
which returns a character string giving a summary re-
presentation of the receiver, and

`storeString`

which returns a character string giving a syntactic re-
presentation of the receiver.

For example,

`#(2 3) printString`

will return the character string '(2 3)',

`#(2 3) storeString`

will return the character string '#(2 3)'.

(Set with: 1 with: 2) printString

will return the character string 'Set(1 2)',

(Set with: 1 with: 2) storeString

will return the character string '(Set new) add: 1;
add: 2; yourself)' which allows an identical copy of the
receiver to be reconstructed.

7.6 Control of errors

The search for a method begins at the level of the class
of the receiver; it continues through the hierarchy of
superclasses. If the method is not found, there is an
error; this is conveyed by the message doesNot-
Understand: with as its argument the message that caused
the error. This method signals the error to the pro-
grammer; it is defined within the class Object and is
therefore accessible to all objects. This method can be
redefined for a particular class, for example, to make
an automatic correction.

There are a number of other methods defined within
class Object that are intended to control errors. These
methods are:

`error:aString`

indicates to the user that there is an error and dis-
plays the string aString,

`primitiveFailed`

indicates to the user that a primitive method has
failed,

`shouldNotImplement`

indicates to the user that the method that should res-
pond exists but should not be used,

`subclassResponsibility`

indicates to the user that the method must be redefined
in the class of the receiver.

7.7 Control of messages

It is sometimes useful to choose which message to send
to an object by computing the selector within an ex-
pression.

One cannot simply write:

`receiver variableSelector`
because the receiver will try to execute the method variableSelector.

There are, however, five methods that are available to deal with this problem:

perform:aSymbol

sends to the receiver the unary message aSymbol,

perform:aSymbol with:anObject

sends to the receiver the keyword or binary message aSymbol with argument anObject,

perform:aSymbol with:anObject with:anOtherObject

sends to the receiver the keyword message aSymbol with arguments anObject and anOtherObject,

perform:aSymbol with: anObject1 with: anObject2 with: anObject3

sends to the receiver the keyword message aSymbol with arguments anObject1, anObject2 and anObject3,

perform:aSelector withArguments: anArray

sends to the receiver the message aSelector with the arguments contained in anArray. There will be an error if the number of elements in the array does not correspond to the number of arguments expected by the selector.

For all the messages, there will be an error if the number of arguments does not match the number expected by the selector. For example,

sort: aSelector

|test|

self size

to: 1

by: -1

do: [:j | 1 to: j - 1 do:

[:k|

test <- (self at:k)

perform: aSelector

with: (self at: k + 1).

test ifFalse:

[self swap: k with: k + 1]]]

is a method for sorting an array, whose argument aSelector is the sort criterion. This method must be defined in the class SequenceableCollection.

#(3 7 0 1) sort: # <

will return the array #(0 1 3 7)

#(3 7 0 1) sort: # >

will return the array #(7 3 1 0).

## 7.8 Dependencies between objects

In the Smalltalk-80 system it is possible to define dependencies between objects in such a way that, when an object is dependent on a second one, any alteration of the second is signalled to the first.
The class Object has defined within it methods that allow dependencies between objects to be created explicitly. These methods are:

`addDependent:anObject`

anObject is added to the list of objects depending on the receiver,

`removeDependent:anObject`

anObject is removed from the list of objects depending on the receiver,

dependents

returns an instance of OrderedCollection containing the objects depending on the receiver,

`release`

removes all the dependencies on the receiver, leaving it with no dependency on any other object,

`changed`

the receiver signals to all its dependent objects that it has changed by sending them the message update,

`changed:aParameter`

the receiver signals to all its dependent objects that it has changed by sending them the message update:aParameter, whose argument aParameter indicates the nature of the change,

`update:aParameter`

is the method that must respond to the message sent by changed or changed:. This method is used to update the receiver,

`broadcast:aMessage`

sends the unary message aMessage to all the objects depending on the receiver,

`broadcast:aMessage with:anObject`

sends the keyword message aMessage with the argument anObject to all the objects depending on the receiver.

We will take as an example the channel-selecting keys of a TV set. Only one of these keys can be selected at once. One key is characterised by its state (selected or not). The class Key of the keys can thus be defined with the following methods

class name

Key

superclass

Object

name of instance variables

selected

class methods

### new

↑super new initialise

instance methods

### initialise

selected <- false

### select

selected ifFalse: [selected <- true self changed]
### update: aKey

```perl
aKey == self ifFalse: [selected <- false]
```

The class `Keyboard` is also defined

```
class name
```

Keyboard

```
superclass
```

Object

```
instance variables name
```

keys

```
class methods
```

### new: numberOfKeys

```perl
↑super new createKeys: numberOfKeys
```

```
instance methods
```

### select: aNumberOfKey

```perl
(keys at: aNumberOfKey) select
```

### createKeys: numberOfKeys

```perl
keys <- Array new: numberOfKeys.
```

```perl
1 to: numberOfKeys do:
```

```perl
    [:index | keys at: index put: Key new].
```

```perl
keys do:
```

```perl
    [:aKey |
```

```perl
keys do:
```

```perl
    [:aDependentKey |
```

```perl
        aKey == aDependentKey ifFalse:
```

```perl
    [aKey addDependent: aDependentKey]]]
```

The method `createKeys:` allows a keyboard to be initialised with a certain number of keys. The created keys are neither selected nor deselected at the start. A key is dependent on all the other keys. Note the pseudo-variable `super` in the method `new:` which avoids recursive calls of this method.

The example can be made to run with:

```
keyboard <- Keyboard new: 5.
```

```
keyboard select: 1.
```

```
keyboard select: 4.
```

Selection of key `1` of the keyboard will cause the message `update:` to be sent to all the other keys, which will deselect them whatever their status.

## 7.9 Primitive messages

There are a certain number of primitive methods described in the class `Object`. These methods are:

```
become:anObject
```

allows the pointers of the receiver and of the argument `anObject` to be exchanged. All the variables that refer to the receiver will refer to the argument and vice versa. There will be an error if one of the two objects is an instance of the class `SmallInteger`,

```
instVarAt: anIndex
```
returns the named instance variable of rank anIndex. The numbering of named instance variables corresponds to their order of definition,

`instVarAt: anIndex put: anObject`

assigns the object anObject to the named instance variable of rank anIndex,

`nextInstance`

returns the instance following the receiver in the list of all instances of the class of the receiver. It returns nil if all the instances have been returned.
# 8 Description of Architecture of Classes

We know that each object is an instance of a class. As a class is itself an object, it is the instance of a class that we call its metaclass. To access the metaclass of a class we send it the message class.

The hierarchy that appears at the level of the metaclasses is the same as that which appears at the level of the classes; that is, if a class A is a subclass of a class B, the metaclass of A will be a subclass of the metaclass of B, as in the diagram below.

<figure><img src="image_13.png" /></figure>

Each metaclass has only one instance and thus there are exactly as many metaclasses as classes. The metaclasses are also objects and thus belong to a class that is called **Metaclass**.

Metaclass is a class and thus has a metaclass which is an instance of Metaclass. Metaclass and its metaclass are both instances of each other.

Object is the only class that does not have a superclass; on the other hand its metaclass has a superclass called **Class**. The diagram below illustrates this architecture.

<figure><img src="image_14.png" /></figure>
## 8.1 Class Behavior

The class **Behavior** defines the elementary methods necessary to objects that have instances. The instances of Behavior are objects representing the classes. As instance variables they have a dictionary of methods, a pointer to a superclass and a list of subclasses.

### 8.1.1 Dictionary of methods

The methods described in a class are held in a dictionary called the dictionary of class methods. The keys to the dictionary are the selectors, and the objects assigned to these keys are methods in compiled form.

#### Creation

The methods that allow the method dictionary to be manipulated are:

* `methodDictionary`: a `Dictionary`

assigns a dictionary to the method dictionary of the receiver;

* `addSelector`: a `Selector` with `Method`: a `Method`

adds a method to the method dictionary of the receiver, with selector `aSelector` and for compiled method `aMethod`;

* `removeSelector`: a `Selector`

removes from the method dictionary of the receiver that method with selector `aSelector`.

#### Compilation

The methods that allow one or more methods to be compiled are:

* `compile`: code

compiles the text of the expressions contained in the argument code. The argument code is a string of characters. An error is produced if the argument code cannot be compiled,

* `compile`: code notifying: requestor

compiles the text of the expressions contained in the argument code. If the argument code cannot be compiled, an error is signalled to the requestor object by a message,

* `recompile`: a `Selector`

compiles the method in the method dictionary whose key is a `Selector`;

* `decompile`: a `Selector`

decompiles the method in the method dictionary whose key is a `Selector`. It returns a string of characters representing the decompiled form of the compiled method;

* `compileAll`

compiles all the methods in the method dictionary;

* `compileAllSubclasses`

compiles all the methods contained in the method dictionaries of the subclasses of the receiver.
## Access to selectors or methods

The methods that allow access to the selectors or methods in the method dictionary are:

### selectors

returns an instance of Set containing the selectors in the method dictionary of the receiver,

### allSelector

returns an instance of Set containing all the selectors in the method dictionary of the receiver and of its superclasses, that is, all the selectors assigned to the messages that are understandable by an instance of the receiver,

### compiledMethodAt: aSelector

returns the compiled method assigned to the selector aSelector contained in the method dictionary of the receiver,

### sourceCodeAt: aSelector

returns a string of characters corresponding to the method assigned to the selector aSelector in the method dictionary of the receiver,

### sourceMethodAt: aSelector

returns an instance of Text corresponding to the method assigned to the selector aSelector in the method dictionary of the receiver. In this book the name of the method is shown in bold type (as are class names).

Some examples of the use of these methods might be:

### Number selectors

returns Set (to:do: even roundTo: storeOn: .... log: tan rounded)

### Number allSelector

returns Set (raisedTo: asPoint between:and: negated ....

min:max: truncated)

### Number sourceCodeAt: #abs

returns:

### 'abs

"Answer a Number that is the absolute value (positive magnitude) of the receiver"

self < 0 ifTrue: [↑self negated]

ifFalse: [↑self]

## Testing

The contents of the methods dictionary can be tested in order to find out the methods that are accessible by the instances of the receiver or the methods that possess certain characteristics. The methods that allow these tests to be carried out are:

### hasMethods

returns true if the methods dictionary of the receiver is not empty,

### includesSelector: aSelector

returns true if the instances of the receiver can res-
pond to the message with selector aSelector, that is, if the selector is a key in the method dictionary of the receiver or of its superclasses,

whichClassIncludesSelector: aSelector

returns the first class contained in the sequence of superclasses of the receiver whose method dictionary contains the key aSelector; it returns nil if no class is found,

whichSelectorAccess: instanceVariableName

returns an instance of Set containing the selectors of the methods in the method dictionary of the receiver that access the instance variable called instance-VariableName,

whichSelectorReferTo: anObject

returns an instance of Set containing the selectors of methods in the method dictionary of the receiver that access the object anObject.

scopeHas: aName ifTrue: aBlock

executes the block aBlock if the variable called aName is accessible by the receiver.

Here are some examples of the use of these methods:

Number hasMethods

returns true because the method dictionary of the class Number is not empty;

Number includesSelector: # ==

returns false because this method is not in the method dictionary of the class Number but in the method dictionary of the class Object;

Number canUnderstand: # ==

returns true because this method is contained in the method dictionary of a superclass of the class Number;

Number whichClassIncludesSelector: # ==

returns class Object.

### 8.1.2 Instances

The instances of a class are created by sending the message new or new: to it. These methods are defined in class Behavior, but can be redefined in any subclass. If a class redefines the method new or new:., the method will necessarily contain the message super new in order to avoid a recursive call of itself. It can be useful to redefine these methods if, for example, you want to initialise instance variables with values other than nil.

#### Creation

The four methods defined in class Behavior that allow instances to be created are:

new

returns a new instance of the receiver. This instance
has no indexed instance variables;

basicNew

is identical to new, but this method must not be redefined;

new: anInteger

returns a new instance of the receiver with a number of indexed instance variables given by anInteger;

basicNew: anInteger

is identical to new:, but this method must not be redefined.

Here are some examples of the use of these methods:

matrix1 <- Array new.

matrix2 <- Array new: 3.

matrix1 is an instance of the class Array which has no indexed instance variables. The message new is equivalent to the message new: 0 for those classes that have indexed instance variables.

## Accessing

There are different methods that allow one or more instances of a class to be accessed. These methods are:

allInstances

returns an instance of OrderedCollection containing all the direct instances of the receiver (without the instances of its subclasses).

someInstance

returns a direct instance of the receiver,

instanceCount

returns the number of direct instances of the receiver,

instVarNames

returns an instance of Array containing the names of the named instance variables,

subclassInstVarNames

returns an instance of Set containing the names of the named instance variables of the subclasses of the receiver,

allInstVarNames

returns an instance of Array containing the names of the named instance variables of the receiver and of its superclasses,

classVarNames

returns an instance of Set containing the names of the class variables of the receiver,

allClassVarNames

returns an instance of Set containing the names of the class variables of the receiver and of all its superclasses,

sharedPools

returns an instance of Set containing the names of the dictionaries that contains the shared variables,

allSharedPools
returns an instance of Set containing the names of the dictionaries that contain the shared variables defined in the receiver and its superclasses.

### Enumeration

There are certain methods that allow an operation to be carried out on each instance. These methods are:

`allInstancesDo: aBlock`

evaluates the block `aBlock` for each instance of the receiver,

`allSubInstancesDo: aBlock`

evaluates the block `aBlock` for all the subclass instances of the receiver.

### Testing

Other methods allow the instance variables of the receiver to be tested

`isPointers`

returns true if the instance variables of the receiver are stored in the form of pointers,

`isBits`

returns true if the instance variables of the receiver are stored in the form of bits,

`isBytes`

returns true if the instance variables of the receiver are stored in the form of bytes,

`isWords`

returns true if the instance variables of the receiver are stored in the form of words,

`isFixed`

returns true if the instances of the receiver have no indexed instance variables,

`isVariable`

returns true if the instances of the receiver have indexed instance variables,

`instSize`

returns the number of named instance variables of the receiver.

Some examples are:

`Number isFixed`

returns true because the instances of `Number` do not have indexed instance variables,

`Array instSize`

returns 0 because the instances of `Array` do not have named instance variables.

### 8.1.3 Manipulation of the class hierarchy

#### Creation

Methods defined in class `Behavior` allow alteration of
the class hierarchy by setting a class's superclass and subclasses. These methods are:

superclass: aClass

fixes the superclass of the receiver at aClass,

addSubclass: aClass

adds the subclass aClass to the receiver,

removeSubclass: aClass

removes the subclass aClass from the receiver.

## Accessing

There are methods that allow the hierarchy of the receiver to be accessed. These are:

subclasses

returns an instance of Set containing the immediate subclasses of the receiver,

allSubclasses

returns an instance of OrderedCollection containing all the subclasses of the receiver, that is, its immediate subclasses and the subclasses of its subclasses, and so on,

withAllSubclasses

returns an instance of OrderedCollection containing the receiver and all of its subclasses,

superclass

returns the superclass of the receiver,

allSuperclasses

returns an instance of OrderedCollection containing the superclass of the receiver followed by the other superclasses in hierarchical order; the last element is always Object.

For example,

Number subclasses

Number allSubclasses

returns OrderedCollection (Fraction Integer Float Small-Integer LargePositiveInteger LargeNegativeInteger),

Integer superclass

returns the object representing the class Number,

Integer allSuperclasses

returns OrderedCollection (Number Magnitude Object).

## Testing

There are certain methods that allow the hierarchy of the receiver to be tested. These methods are:

inheritsFrom: aClass

returns true if the class aClass belongs to the sequence of subclasses of the receiver,

kindOfSubclass

returns a string describing the type of the receiver.

There are four types of class in Smalltalk-80:

- classes which have no indexed instance variables
where the named instance variables represent pointers to
other objects; the returned string will be 'subclass:'

- those classes which have indexed instance variables
that can represent

- pointers; the returned string will be

'variableSubclass:'

- bytes; the returned string will be

'variableByteSubclass:'

- words; the returned string will be

'variableWordSubclass:'

For example:

Integer inheritsFrom: Number
returns true because Number is the superclass of Integer,

Integer kindOfSubclass
returns 'subclass:'

Float kindOfSubclass
returns 'variableWordSubclass:'.

Enumeration

There are certain methods that allow operations to be
carried out on a part of the class hierarchy related to
the receiver. These methods are:

allSubclassesDo: aBlock

evaluates the block aBlock for all the subclasses of the
receiver, that is, for its immediate subclasses and the
subclasses of its subclasses, and so on

allSuperclassesDo: aBlock

evaluates the block aBlock for all the superclasses of
the receiver,

selectSubclasses: aBlock

evaluates the block aBlock for all the subclasses of the
receiver and groups in an instance of Set all the
classes for which evaluation returns true. This instance
of Set is returned.

selectSuperclasses: aBlock

evaluates the block aBlock for all the superclasses of
the receiver and groups in an instance of Set all the
classes for which evaluation returns true. This instance
of Set is returned.

8.2 The classes ClassDescription and Class

The description of a class is not totally described by
the class Behavior. Behavior does not allow the names of
instance variables and class variables to be stored; nor
does it allow a name to be given to the class or a
comment describing the class to be stored.

The class ClassDescription, which is a subclass of
the class Behavior, and the class Class, which is a sub-
class of the class ClassDescription, are the classes
that allow a name to be given to a class, a comment to be assigned to it and the names of named instance variables to be stored.

### 8.2.1 Access to the description of a class

The additional methods that allow access to the description of a class are:

name

returns a string representing the name of the receiver,

comment

returns a string giving the comment assigned to the receiver,

comment: aString

assigns the string aString to the commentary associated with the receiver,

addInstVarName: aString

adds to the list of named instance variables of the receiver the named instance variable whose name is aString,

removeInstVarName: aString

removes from the list of named instance variables of the receiver the named instance variable whose name is aString. It returns an error if aString is not the name of a named instance variable.

### 8.2.2 Category of classes and messages

To clarify the description of the class hierarchy, the classes are grouped into categories. This grouping is arbitrary and simply allows classes that relate to the same problem to be grouped together; for example, the category Numeric-Numbers groups classes Number, Integer, Float, Fraction, SmallInteger, LargePositiveInteger, LargeNegativeInteger, Random. This grouping has no effect on the hierarchy of the classes.

Just as classes can be grouped into categories, so can the methods of classes.

The methods that allow access to the category of a class or a method are:

category

returns the category of the receiver,

category: aString

assigns to the category of the receiver the string aString,

removeCategory: aString

removes all the methods from the methods dictionary of the receiver whose category is aString,

whichCategoryIncludesSelector: aSelector

returns the category of the method whose selector is aSelector; it returns nil if the method is not found in the method dictionary of the receiver.
### 8.2.3 Copy of messages

Some methods are provided that copy one or more methods from another class. These methods are:

**copy**: aSelector from: aClass

copies the method of selector aSelector described in the class aClass and places it in the method dictionary of the receiver,

**copy**: aSelector from: aClass classified: aCategory

copies the method of selector aSelector described in the class aClass and places it in the method dictionary of the receiver under category aCategory,

**copyAll**: arrayOfSelector from: aClass

copies the methods whose selectors are contained in the arrayOfSelector described in the class aClass and places them in the method dictionary of the receiver,

**copyAll**: arrayOfSelector from: aClass classified:

aCategory

copies the methods whose selectors are contained in the arrayOfSelector described in the class aClass and places them in the method dictionary of the receiver under the category aCategory,

**copyAllCategoriesFrom**: aClass

copies all the methods described in the class aClass and places them in the method dictionary of the receiver,

**copyCategory**: aCategory from: aClass

copies all the methods described in the class aClass under the category aCategory and places them in the method dictionary of the receiver,

**copyCategory**: aCategory from: aClass classified:

aNewCategory

copies all the methods described in the class aClass under the category aCategory and places them in the method dictionary of the receiver under the category aNewCategory.

### 8.2.4 Compilation of methods

There are two particular methods that allow source code to be compiled and the result placed under a category. These two methods are:

**compile**: aSourceCode classified: aCategory

compiles the text of the expressions contained in the argument aSourceCode and places the compiled method obtained in the method dictionary of the receiver under category aCategory. An error is indicated to the programmer if the argument aSourceCode cannot be compiled:

**compile**: aSourceCode classified: aCategory requestor:

aRequestor

compiles the text of the expressions contained in the argument aSourceCode and places the compiled method obtained in the methods dictionary of the receiver under category aCategory. An error is sent to the argument
aRequestor if the argument aSourceCode cannot be compiled.

### 8.2.5 Access to variable names

Three methods allow variable names to be returned in the form of strings. These three methods are:

`classVariablesString`

returns a string of characters containing the names of all the class variables of the receiver,

`instanceVariablesString`

returns a string of characters containing the names of all the instance variables of the receiver,

`sharedPoolsString`

returns a string of characters containing the names of all the dictionaries that contain the shared variables of the receiver.

### 8.2.6 Saving a class on a file

Three methods allow the description of a class to be saved on a file. These methods are:

`fileOutOn: aFile`

saves the description of the receiver on the file `aFile` which is an instance of the class `生活的流`, `fileOutCategory: aCategoryName`

creates a file whose name is the name of the receiver concatenated to the string `'st'` and places in it all the methods whose category is `aCategoryName`,

`fileOutChangedMessages: aListOfChanges on: aFile`

the argument `aListOfChanges` is made up of `class `/`message` couplets; it is an instance of the class `Set`. The description of the couplets `class `/`message` is saved on the file `aFile`, which is an instance of the class `生活的流`.

The class `ClassDescription` possesses another subclass called `Metaclass`.

## 8.3 The class Metaclass

The metaclasses are instances of the class `Metaclass`. We have seen that the role of a metaclass is to allow the initialisation of class variables and the creation of instances of the class that is assigned to it. Each metaclass contains an instance variable called `thisClass` which allows its unique instance to be referenced.

## 8.4 Multiple inheritance

We have seen that a class inherits variables and methods from its superclass. In the general case a class may inherit from a single other class (this is so for all the classes of the Smalltalk system), but it is also possible for a class to inherit from several other classes; this is called multiple inheritance.
Multiple inheritance allows the properties of two or more existing classes in the system to be fused into one class. Multiple inheritance imposes certain additional constraints that arise from the conflicts that may appear between the different superclasses:

- A class cannot inherit from two classes that have a same instance variable (that is, a variable having the same name).

- When creating a class with multiple superclasses, there may be a conflict between different inherited methods with the same name. When this occurs, a new method with the same name is automatically created in the new class which signals an error if activated. If the user wishes to resolve the conflict, he should edit the new method to call one of the inherited methods, designating the method by its name, prefixed with the name of its class and a full stop. For example:

Point.

designates the method of addition of two points.

To implement multiple inheritance, the Smalltalk system possesses a subclass of Metaclass called **Metaclass-ForMultipleInheritance**, whose instances have an instance variable called otherSuperclasses which contains the list of additional superclasses. The metaclasses of multiple inheritance classes are instances of **MetaclassForMultipleInheritance**.

To create a class that inherits from several other classes the following message must be sent to the class **Class**

named: aSymbol

superclass: namesOfSuperclasses

instVariableNames: namesOfInstanceVariables

classVariableNames: namesOfClassVariables

category: nameOfCategory

For example, consider the case of simulating a transport network in which the following two classes are defined:

MotorVehicle

which has two instance variables, namely:

tankCapacity and operatingHours

WheeledVehicles

which has one instance variable:

mileage

The class Automobile embraces the two aspects of classes MotorVehicle and WheeledVehicles; thus, to define it we need to construct it as the subclass of these two classes:

Class named: #Automobile

superclasses: 'MotorVehicle WheeledVehicles'

instVariableNames: ' numberOfSeats '

classVariablesNames: ''
category: 'simulation-network'

Those methods that conflict will have to be redefined; for example, the method printOn: which generates a textual representation of an object.

For multiple inheritance to be attractive to use, the number of conflicting methods needs to be small; that is, the two superclasses should have few aspects in common.
# 9 The Magnitude Classes

The magnitude classes contain the objects on which an ordering relation can be established. They are objects for which the concept of size has a meaning.

## 9.1 The class Magnitude

The class Magnitude is a subclass of the class Object. All the ordered classes are subclasses of Magnitude; this is why Magnitude describes comparison methods that may be used by all the instances of its subclasses.

These methods are:

`< aSize`

returns true if the receiver is less than the argument aSize,

`<= aSize`

returns true if the receiver is less than or equal to the argument aSize,

`> aSize`

returns true if the receiver is greater than the argument aSize,

`>= aSize`

returns true if the receiver is greater than or equal to the argument aSize,

`between: min and: max`

returns true if the receiver is greater than or equal to the argument min and less than or equal to the argument max,

`min: aSize`

returns the minimum of the receiver and the argument aSize,

`max: aSize`

returns the maximum of the receiver and the argument aSize,

`= aSize`

this message must be redefined in subclasses of Magnitude. In class Magnitude the method = is described by the unique expression self subclassResponsibility.

For example:

`2 > 1` returns true

`1 > 2` returns false

`2 between: 1 and: 3` returns true

`2 min: 5` returns 2

`2 max: 5` returns 5
## 9.2 The class Date

The class Date is a subclass of Magnitude. Its instances are dates that represent a day, a month and a year of the calendar. It knows the days of the week and the months of the year by storing index/name pairs.

There are a number of methods that allow these dates to be manipulated.

### 9.2.1 Creation of instances

When a new date is created, it is initialised with special values. The different creation methods are:

today

returns a new instance of the class Date representing today's date,

fromDay: numberOfDays

returns a new instance of Date representing the date obtained by adding numberOfDays to the first of January 1901,

newDay: aDay month: aMonth year: aYear

returns a new instance of Date whose day is aDay, the month aMonth and the year aYear. The arguments aDay and aYear are integers, whereas the argument aMonth is a symbol.

newDay: numberOfDays year: aYear

returns a new instance of Date representing the date obtained by adding numberOfDays to the first of January of the year aYear.

For example:

<table><tr><td>Date today</td><td>returns 22 October 1986</td></tr><tr><td>Date fromDays: 3</td><td>returns 4 January 1901</td></tr><tr><td>Date newDay: 8 month: #Oct year: 86</td><td>returns 8 October 1986</td></tr><tr><td>Date newDay: 3 year: 86</td><td>returns 4 January 1986</td></tr></table>

### 9.2.2 Information about the calendar

It is possible to obtain general information about the calendar through the following methods:

dayOfWeek: nameOfDay

returns the number of the day nameOfDay in the week (1 for #Monday, etc),

nameOfDay: aNumber

returns a symbol representing the day of the week with number aNumber,

indexOfMonth: nameOfMonth

returns the number of the month nameOfMonth in the year (1 for #January or #Jan, etc). The name of a month can be abbreviated,

nameOfMonth: aNumber

returns a symbol representing the month of the year of number aNumber,
**daysInMonth**: nameOfMonth forYear: aYear
returns the number of days of the month nameOfMonth for the year aYear,
**daysInYear**: aYear

returns the number of days of the year aYear,

**leapYear**: aYear

returns 1 if the year is a leap year, otherwise 0,
**dateAndTimeNow**

returns an instance of Array whose first element is the actual date and second element the actual time.

For example:

<table><tr><td>Date dayOfWeek: #Tuesday</td><td>returns 2</td></tr><tr><td>Date nameOfDay: 3</td><td>returns Wednesday</td></tr><tr><td>Date indexOfMonth: #Mar</td><td>returns 3</td></tr><tr><td>Date nameOfMonth: 4</td><td>returns April</td></tr><tr><td>Date daysInMonth: #February</td><td>forYear: 1984</td></tr><tr><td></td><td>returns 29</td></tr><tr><td>Date daysInYear: 1984</td><td>returns 366</td></tr><tr><td>Date leapYear: 1984</td><td>returns 1</td></tr><tr><td>Date dateAndTimeNow</td><td>returns (a Date a Time)</td></tr></table>

### 9.2.3 Arithmetic

There are three methods for carrying out arithmetic operations on dates. These methods are:

**addDays**: numberOfDays

returns a date obtained by adding numberOfDays to the receiver,

**subtractDays**: numberOfDays

returns a date obtained by subtracting numberOfDays from the receiver,

**subtractDate**: aDate

returns the number of days separating the receiver from the argument aDate.

For example:

<table><tr><td>Date today addDays: 10</td><td>returns 1 November 1986</td></tr><tr><td>Date today subtractDays: 10</td><td>returns 12 October 1986</td></tr><tr><td>Date today subtractDate:</td><td></td></tr><tr><td>(Date newDay: 5 month: #Oct year: 1986)</td><td>returns 17</td></tr></table>

### 9.2.4 Conversion

In order to be able to carry out calculations on dates and hours both are converted into seconds. The method that allows a date to be converted into seconds is:

**asSeconds**

which returns the number of seconds that have elapsed since 1 January 1901 up to the beginning of the current day.
### 9.3 The class Time

The class Time is a subclass of the class Magnitude. The instances of Time represent an instant of a day.

#### 9.3.1 Creation of instances

Three methods allow an instance of Time to be created. These three methods are:

now

returns an instance of Time representing the current time,

fromSeconds: numberOfSeconds

returns an instance of Time representing the time calculated by adding numberOfSeconds to midnight:

dateAndTimeNow

returns an instance of Array whose first element is the actual date and whose second element is the actual time.

#### 9.3.2 Information about the time

The class Time can respond to a certain number of general messages about the time:

millisecondsClockValue

returns the number of milliseconds since the clock passed zero,

millisecondsToRun: aBlock

returns the number of milliseconds it takes to execute the block aBlock,

timeWords

returns the number of seconds that have elapsed since 1 January 1901 at the Greenwich meridian.

totalSeconds

returns the number of seconds that have elapsed since 1 January 1901, allowing for corrections for time zones and summertime.

#### 9.3.3 Conversions

In order to be able to carry out calculations on dates and times, it is useful to be able to convert these into seconds. The method that allows this to be done is:

asSeconds

returns the number of seconds that have elapsed since midnight.

#### 9.3.4 Arithmetic

Two methods allow arithmetic operations to be carried out on times. These are:

addTime: aPeriod

returns an instance of Time representing the time calculated by adding aPeriod to the receiver. The argument aPeriod must be an instance of Date or of Time,

subtractTime: aPeriod
returns an instance of Time representing the time calculated by subtracting aPeriod from the receiver. The argument aPeriod must be an instance of Date or of Time.

## 9.4 The class Character

The class Character is also a subclass of the class Magnitude. It is an ordered class because the instances of this class represent ASCII codes. There are therefore 256 instances in this class; they belong to the Small-talk system and cannot be altered. It is not possible to make new Characters.

### 9.4.1 Access to the instances

The methods that allow access to the instances of the class Character are:

value: anInteger

returns the Character with ASCII code anInteger,

digitValue: anInteger

returns the character representing the digit corresponding to anInteger (when anInteger is greater than 9, it

returns the first letters of the alphabet),

asciiValue

returns the ASCII code of the receiver,

digitValue

returns the number corresponding to the digit represented by the receiver.

For example:

Character value: 67 returns $C

Character digitValue: 1 returns $1

Character digitValue: 10 returns $A

$A asciiValue returns 65

$B digitValue returns 11

### 9.4.2 Testing the instances

The following methods test for the nature of the instances of the class Character:

isAlphaNumeric

returns true if the receiver is a letter or a digit,

isDigit

returns true if the receiver is a digit (0-9),

isLetter

returns true if the receiver is a letter,

is Lower Case

returns true if the receiver is a lower case letter,

isUppercase

returns true if the receiver is an upper case letter,

isSeparator

returns true if the receiver is one of the separator

characters (cr, tab, line feed, form feed),

isVowel

returns true if the receiver is an upper or lower case vowel.
For example:

<table><tr><td>$+ isAlphaNumeric</td><td>returns false</td></tr><tr><td>$2 isDigit</td><td>returns true</td></tr><tr><td>$t isLetter</td><td>returns true</td></tr><tr><td>$G isLowerCase</td><td>returns false</td></tr><tr><td>$G isUppercase</td><td>returns true</td></tr><tr><td>$; isSeparator</td><td>returns false</td></tr><tr><td>$a isVowel</td><td>returns true</td></tr></table>

The following chapter describes another subclass of Magnitude, namely the class Number.
# 10 The Numeric Classes

The instances of the numeric classes are the objects that we use to carry out arithmetic operations or mathematical calculations. Each type of numeric value is represented by a class. All the numeric classes are subclasses of class `Number` which has three direct subclasses.

- the class `Float`

- the class `Fraction`

- the class `Integer`.

The class `Integer` has three subclasses

- the class `SmallInteger`

- the class `LargePositiveInteger`

- the class `LargeNegativeInteger`.

The classes `Number` and `Integer` are abstract subclasses, that is, they have no direct instance.

## 10.1 The class Number

A certain number of messages are understood by all the numeric objects. These messages allow arithmetic operations and comparisons to be made. The majority of these messages are redefined in the subclasses of class `Number`. The messages common to all the subclasses of class `Number` are described below.

### 10.1.1 Arithmetic

The messages allowing arithmetic operations on numbers to be carried out are:

**`+ aNumber`**

returns the sum of the receiver and the argument `aNumber`,

**`- aNumber`**

returns the difference between the receiver and the argument `aNumber`,

**`* aNumber`**

returns the product of the receiver and the argument `aNumber`,

**`/ aNumber`**

returns the quotient between the receiver and the argument `aNumber`. If the division is not whole the result is an instance of the class `Fraction`,
// aNumber

returns the whole part of the division of the receiver
by the argument aNumber,

\\ aNumber

returns the whole part of the remainder of the division
of the receiver by the argument aNumber,

abs

returns the absolute value of the receiver,
negated

returns the opposite of the receiver,

quo: aNumber

returns the whole part of the division of the receiver
by the argument aNumber,

rem: aNumber

returns the whole part of the remainder of the division
of the receiver by the argument aNumber,

reciprocal

returns the inverse of the receiver, producing an error
if the receiver is equal to 0.

For example:

<table><thead><tr><th>Expressions</th><th>Results</th></tr></thead><tbody><tr><td>2 + 3</td><td>5</td></tr><tr><td>2 - 3</td><td>-1</td></tr><tr><td>2 * 3</td><td>6</td></tr><tr><td>4/2</td><td>2</td></tr><tr><td>4/3</td><td>(4/3) instance of the class Fraction with denominator 3 and numerator 4</td></tr><tr><td>4//3</td><td>1</td></tr><tr><td>-4//3</td><td>-2</td></tr><tr><td>4 \ 3</td><td>1</td></tr><tr><td>-4 \ 3</td><td>1</td></tr><tr><td>-5 abs</td><td>5</td></tr><tr><td>5 negated</td><td>-5</td></tr><tr><td>-4 quo: 3</td><td>-1</td></tr><tr><td>-4 rem: 3</td><td>-1</td></tr><tr><td>7 reciprocal</td><td>(1/7)</td></tr></tbody></table>

### 10.1.2 Mathematics

The messages that allow mathematical operations to be
carried out on numbers are:

exp

returns the exponent of the receiver,

ln

returns the naperian logarithm of the receiver,

log: aNumber
returns the logarithm to base aNumber of the receiver,
`floorLog: aNumber`

returns the whole part of the logarithm to base aNumber
of the receiver,
`raisedTo: aNumber`

returns the receiver raised to the power aNumber,
`raisedToInteger: anInteger`

returns the receiver raised to the power anInteger. The
argument anInteger must be an instance of class Integer.
`sqrt`

returns the square root of the receiver,
`squared`

returns the square of the receiver,
`sin`

returns the sine of the receiver expressed in radians,
`cos`

returns the cosine of the receiver expressed in radians,
`tan`

returns the tangent of the receiver expressed in
radians,
`arcSin`

returns the arcsine of the receiver in radians,
`arcCos`

returns the arccosine of the receiver in radians,
`arcTan`

returns the arctangent of the receiver in radians.
For example:

<table><thead><tr><td>Expressions</td><td>Results</td></tr></thead><tbody><tr><td>1 exp</td><td>2.71828</td></tr><tr><td>1 ln</td><td>0.0</td></tr><tr><td>2 log: 2</td><td>1.0</td></tr><tr><td>3 floorLog: 2</td><td>1.0</td></tr><tr><td>4 raisedTo: 2.4</td><td>27.8576</td></tr><tr><td>4 raisedToInteger: 3</td><td>64</td></tr><tr><td>2 sqrt</td><td>1.41421</td></tr><tr><td>9 squared</td><td>81</td></tr></tbody></table>

### 10.1.3 Tests

There are the following messages that allow the characteristics of a number to be tested.

even

returns true if the receiver is an even number,
`odd`

returns true if the receiver is an odd number,
`negative`

returns true if the receiver is negative,
`positive`

returns true if the receiver is positive or zero,
`strictlyPositive`
returns true if the receiver is strictly positive,
sign

returns 1 if the receiver is strictly positive; -1 if it
is strictly negative; 0 if it is zero.

### 10.1.4 Truncation and rounding

Several messages allow a number to be truncated or rounded. These messages are:

ceiling

returns the smallest integer greater than or equal to
the receiver,

floor

returns the largest integer less than or equal to the
receiver (that is, its whole part),

truncated

returns the receiver without its decimal part,

truncateTo: aNumber

returns the largest multiple of the argument aNumber
whose absolute value is less than or equal to the absolute value of the receiver,

rounded

returns the integer closest to the receiver,

roundTo: aNumber,

returns the multiple of the argument aNumber closest to
the receiver.

For example:

<table><thead><tr><td>Expressions</td><td>Results</td></tr></thead><tbody><tr><td>2.3 ceiling</td><td>3</td></tr><tr><td>-2.3 ceiling</td><td>-2</td></tr><tr><td>2.3 floor</td><td>2</td></tr><tr><td>-2.3 floor</td><td>-3</td></tr><tr><td>2.3 truncated</td><td>2</td></tr><tr><td>-2.3 truncated</td><td>-2</td></tr><tr><td>2.3 truncateTo: 0.7</td><td>2.1</td></tr><tr><td>-2.3 truncateTo: 0.7</td><td>-2.1</td></tr><tr><td>2.3 rounded</td><td>2</td></tr><tr><td>2.6 rounded</td><td>3</td></tr><tr><td>-2.3 rounded</td><td>-2</td></tr><tr><td>-2.6 rounded</td><td>-3</td></tr><tr><td>2.3 roundTo: 0.7</td><td>2.1</td></tr><tr><td>2.6 roundTo: 0.7</td><td>2.8</td></tr></tbody></table>

### 10.1.5 Conversions

A number can represent an angle expressed either in
degrees or in radians. Two messages allow conversions of
angles to be made:

degreesToRadians

the receiver being expressed in degrees, it returns a
number representing the receiver expressed in radians,
radiansToDegrees

the receiver being expressed in radians, it returns a
number representing the receiver expressed in degrees.

### 10.1.6 Nature of the object returned by arithmetic operations

Arithmetic operations can be broken down into two categories.

- Those in which the argument and the receiver are instances of the same class, for example:

$$2 + 3$$

- Those in which the argument and the receiver are not instances of the same class, for example:

$$2.2 + 3$$

When the receiver and the argument are instances of the same class, one is able to determine the class of the result. Depending on the values represented by the argument and the receiver, the result returned may belong to different classes.

For example:

8/4 returns 2, an instance of class Integer

8/3 returns (8/3), an instance of class Fraction.

When the receiver and the argument are not instances of the same class, one of the operands must be transformed to get back to the preceding case. The transformation must be made with the minimum loss of data. The answer is therefore to transform the item that contains the minimum of data.

Thus a hierarchy of numbers can be defined depending on their generality. This is as follows:

Float

Fraction

LargePositiveInteger LargeNegativeInteger

SmallInteger

All numbers can be represented by instances of the class Float (see below), but the precision is not infinite.

There are three messages for making conversions:

coerce: aNumber

returns a number representing the number aNumber that is an instance of the same class as the receiver. This method must be defined in each subclass of Number.

generality

returns the degree of generality of the receiver,

retry: aSelector coercing: aNumber

the receiver and the argument not being instances of the same class, the least general must be converted, then the selector message aSelector must be re-evaluated. For example, in the expression

3.7*2
the argument 2 and the receiver 3.7 are not instances of
the same class. Evaluation of the expression will then
look like

3.7 retry #* coercing: 2

which will transform 2 into 2.0 and will return the
result 7.4.

## 10.2 The class Float

The instances of class Float represent real numbers with
a finite precision and lying between two limiting
values. For example, the precision may be to 6 figures,
with the numbers lying between 10<sup>-32</sup> and 10<sup>32</sup>.

Some examples of floating number are:

1.2 -1.2 2.le4 -2.le4

Whenever one of the operands in an arithmetic expression is a Float, the result is a Float.

## 10.3 The class Fraction

The instances of the class Fraction represent rational
numbers. This representation is exact; a fraction has an
integer numerator and denominator. The instances of the
class Fraction can be obtained in an arithmetic ex-
pression when one of the operands is a fraction and the
other is not a floating number (cf 10.1.6 and 10.2).
Instances of class Fraction can also be obtained by div-
iding two integers, when the numerator is not an exact
multiple of the denominator.

## 10.4 The class Integer

The instances of class Integer represent integer num-
bers. This class has three subclasses which are:

SmallInteger

which represents integers whose absolute value is less
than a limit which allows for compact storage (typically
in one word less 1 bit),

LargePositiveInteger

which represents arbitrarily large positive integers,

LargeNegativeInteger

which represents arbitrarily large negative integers,

Calculations are much more costly when they involve
instances of the classes LargePositiveInteger and Large-
NegativeInteger.

If an operation on two instances of the class Small-
Integer gives a result outside the limits of the class,
the result is transformed into a LargePositiveInteger or
a LargeNegativeInteger.

### 10.4.1 Enumeration

There is a method for evaluating a block several times.

This is

timesRepeat: aBlock
which evaluates the block `aBlock` a number of times equal to the receiver. For example:

`a <- 1.`

`5 timesRepeat: [a <- a/20 + a reciprocal]`

assigns to a the value 1 and then evaluates the block 5 times. The final value of a is 1.41421 (close to the square root of 2).

### 10.4.2 Some additional arithmetic functions

The class `Integer` contains some arithmetic functions that belong to integers. The messages that relate to these functions are:

`factorial`

returns the factorial of the receiver, which must not be negative,

`gcd: anInteger`

returns the greatest common divisor of the receiver and the argument `anInteger`,

`lcm: anInteger`

returns the largest common multiple of the receiver and the argument `anInteger`.

### 10.4.3 Bit manipulation

An integer can be interpreted as a sequence of bits (the representation of the integer expressed to the base 2).

Some messages allow access to these bits. These are:

`allMask: anInteger`

returns true if all the bits set in the argument `an-Integer` are also set in the receiver,

`anyMask: anInteger`

returns true if at least one of the bits set in the argument `anInteger` is also set in the receiver,

`noMask: anInteger`

returns true if none of the bits set in the argument `anInteger` is set in the receiver,

`bitAnd: anInteger`

returns an integer whose bits are obtained by making a logical "and" between the corresponding bits of the argument `anInteger` and the receiver,

`bitOr: anInteger`

returns an integer whose bits are obtained by a logical "or" between the corresponding bits of the argument `anInteger` and the receiver,

`bitXor: anInteger`

returns an integer whose bits are obtained by making an "exclusive or" between the corresponding bits of the argument `anInteger` and the receiver,

`bitAt: anIndex`

returns the receiver bit positioned at `anIndex`,

`bitInvert`

returns an integer whose bits are complements of the
receiver bits,

highBit

returns the position of the most significant bit of the receiver or the number of bits necessary to represent the receiver to base 2,

bitShift: anInteger

returns an integer (in two's complement) obtained by shifting the receiver bits (in two's complement) of anInteger to the left.

For example:

Expressions Results

2r1010 10

2r1000 8

10 allMask: 8 true

8 allMask: 10 false

8 anyMask: 10 true

10 noMask: 8 false

10 bitAnd: 8 8

10 bitOr: 8 10

10 bitXor: 8 2

10 bitAt: 3 0

10 bitInvert -11

10 highBit 4

10 bitShift: 2 40

### 10.4.4 Changing base

We have seen how a number could be expressed to another base. There is a message to do this:

radix: anInteger

returns a representation to base anInteger of the receiver. For example:

2 radix: 2 returns 2r10

9 radix: 3 returns 3r100

4r10 radix: 2 returns 2r100
# 11 The Class Collection

A collection represents a set of objects that are not necessarily of the same kind.

Most of the subclasses of **Collection** use indexed instance variables. Indexed instance variables are accessed by an index.

The class **Collection** is an abstract class that describes the behaviour of all collections. It supports four categories of message described below.

## 11.1 Creation of instances

Some collections can be expressed in literal form (see chapter 5). For example

```python
#(1 5 3 4)
```

represents an instance of Array with four elements,

‘this is a string’

represents an instance of String with 16 elements.

The usual messages for creating an instance of a Smalltalk-80 class are new and new:. These messages are also usable for instances of the class Collection. However, there are additional messages allowing the creation of new collections in which the elements are initialised on creation. These messages are:

with: anObject

returns a new instance of the receiver containing the single element anObject,

with: aFirstObject with: aSecondObject

returns a new instance of the receiver containing the two elements aFirstObject and aSecondObject,

with: aFirstObject with: aSecondObject with: aThirdObject

returns a new instance of the receiver containing the three elements aFirstObject, aSecondObject and aThirdObject,

with: aFirstObject with: aSecondObject with: aThirdObject with: aFourthObject

returns a new instance of the receiver containing the four elements aFirstObject, aSecondObject, aThirdObject and aFourthObject.
For example:

Array with: 1 with: 5 with: 3 with: 4
is equivalent to # (1 5 3 4).

String with: $a with: $b with: $c
is equivalent to 'abc'.

## 11.2 Manipulating the elements of a collection

### 11.2.1 Adding elements to a collection

There are two messages that allow elements to be added to a collection. They are:

add: anObject

adds to the receiver the element anObject,

all: aCollection

adds to the receiver all the elements of the collection

For example:

<table><thead><tr><td>Expressions</td><td>Contents of a</td></tr></thead><tbody><tr><td>a <- Bag new.</td><td>Bag ()</td></tr><tr><td>a add: $a.</td><td>Bag ($a)</td></tr><tr><td>a addAll: #(2 3 $b)</td><td>Bag ($a 2 3 $b)</td></tr></tbody></table>

### 11.2.2 Removing elements from a collection

Just as you can add elements to a collection, so you can remove them. There are three messages that allow elements to be removed from a collection. They are:

remove: anObject

removes one of the occurrences of the element anObject from the receiver and returns the object anObject. If no occurrence is found, an error is produced.

remove: anObject ifAbsent: aBlock

removes one of the occurrences of the element anObject from the receiver and returns the object anObject. If no occurrence is found, the block aBlock is evaluated.

removeAll: aCollection

removes an occurrence of each element of the collection aCollection. If, for an element of the collection aCollection, there is no occurrence in the receiver, an error is generated. If not, the collection aCollection is returned.

For example:

<table><thead><tr><td>Expressions</td><td>Contents of a</td></tr></thead><tbody><tr><td>a</td><td>Bag ($a 2 3 $b)</td></tr><tr><td>a remove: $a</td><td>Bag (2 3 $b)</td></tr><tr><td>a remove: $a ifAbsent: [a add: $b]</td><td>Bag ($b 2 3 $b)</td></tr><tr><td>a removeAll: #(2 $b)</td><td>Bag (3 $b)</td></tr></tbody></table>
### 11.3 Tests on a collection

Three messages allow collections to be tested. These are:

* `includes: anObject`

returns true if the object `anObject` is equal to one of the elements of the receiver,

* `empty`

returns true if the receiver is an empty collection,

* `occurrencesOf: anObject`

returns the number of elements of the receiver equal to the argument `anObject`.

For example:

<table><thead><tr><td>Expressions</td><td>Result</td></tr></thead><tbody><tr><td>a</td><td>Bag ($a 2 3 $b $b)</td></tr><tr><td>a includes: 2</td><td>true</td></tr><tr><td>a empty</td><td>false</td></tr><tr><td>a occurrencesOf: $b</td><td>2</td></tr></tbody></table>

### 11.4 Enumeration of a collection

A collection generally includes several elements. There are several messages described in the class `Collection` that allow each element of a collection to be accessed and allow an operation to be performed on this element.

These messages are:

* `do: aBlockWithOneArgument`

evaluates the block `aBlock` for each element of the receiver, the element being the argument of the block,

* `select: aBlockWithOneArgument`

evaluates the block `aBlock` for each element of the receiver and returns a collection of the same class as the receiver, containing those elements for which evaluation of the block has returned true,

* `reject: aBlockWithOneArgument`

evaluates the block `aBlock` for each element of the receiver and returns a collection of the same class as the receiver, containing those elements for which evaluation of the block has returned false,

* `detect: aBlockWithOneArgument`

evaluates the block `aBlock` for each element of the receiver and returns the first element of the receiver that evaluation of the block has returned as true. If no element is found, an error is produced.

* `detect: aBlock ifNone: anOtherBlock`

evaluates the block `aBlock` for each element of the receiver and returns the first element of the receiver that evaluation of the block `aBlock` has returned as true. If no element is found, the block `anOtherBlock` is evaluated.
inject: anInitialValue into: aBlockWithTwoArguments evaluates the block aBlockWithTwoArguments for each element of the receiver. The second argument of the block is the element, the first argument of the block is the result of its preceding evaluation. At first evaluation, the first argument is anInitialValue.

For example:

sum <- 0

a <- # (1 2 3 4 5).

a do: [:anElement | sum <- sum +anElement].

places in the variable sum the sum of all the elements in the array a;

a <- # (1 2 3 4 5).

a select: [:anElement | anElement even].

returns Array (2 4);

a reject: [:anElement | anElement even]

returns Array (1 3 5);

a detect: [:anElement | anElement > 2.5]

returns 3;

a detect: [:anElement | anElement > 5] ifNone: ['Element not found']

returns 'Element not found';

a inject: 10 into: [:initialValue: anElement |

initialValue + anElement]

returns 25. On the first evaluation of the block, initialValue is 10, anElement is 1; the result of the evaluation of the block, which is also the result of the evaluation of its last expression, is 11. On the second evaluation, initialValue is 11, anElement is 2, and so on.

The message inject: into: allows a local variable to be initialised in the message that will be passed between the successive evaluations of a block. To write the previous example without inject: into:, one could write, for example:

counter <- 10.

a do: [:anElement | counter <- counter + anElement]

## 11.5 Conversion of a collection

Five messages understood by the instances of class Collection transform instances of a subclass of class Collection to instances of another subclass of class Collection.

asBag

returns an instance of class Bag whose elements are those of the receiver,

asSet

returns an instance of class Set whose elements are those of the receiver (an instance of class Set does not possess two equal elements),

asOrderedCollection
returns an instance of class OrderedCollection whose
elements are those of the receiver,

`asSortedCollection`

returns an instance of class SortedCollection whose
elements are those of the receiver (the elements are
stored in ascending order),

`asSortedCollection: aBlock`

returns an instance of class SortedCollection whose
elements are those of the receiver (the criterion for
the order of the elements being given by the evaluation
of the block aBlock).

## 11.6 The subclasses of the class Collection

Class Collection has no instances; that is, it is an abstract class. It possesses several subclasses that allow the different structures of useful data to be represented. These subclasses are arranged in the following hierarchy.

### 11.6.1 The class Bag

Class Bag is a subclass of class Collection. The elements of an instance of Bag represent an arbitrary set whose elements are not accessible by keys. Because of this, the messages at: and at: put: are not understood by the instances of class Bag. In fact, an instance of the class Bag just represents a group of elements. There is only one additional message that is understandable by the instances of this class. It is as follows:

`add: anObject withOccurrences: anInteger`
adds to the receiver a number of occurrences of anObject equal to anInteger.

### 11.6.2 The class Set

Class Set is also a subclass of class Collection. In contrast to the instances of class Bag, those of class Set cannot contain two equal elements.

### 11.6.3 The class Dictionary

Class **Dictionary** is a subclass of class Set. The elements of an instance of class **Dictionary** are instances of class **Association**. An instance of class **Association** is represented by a pair of objects; the first element is called the key, the second element is called the value assigned to the key.

The messages at: and at: put: are still defined for the instances of this class; however, their methods have been redefined. In contrast to the foregoing, the argument of the keyword at: is no longer a numeric index but any object that represents a key.

The additional messages that can be understood by the instances of class **Dictionary** are as follows.
### Access

`at: aKey ifAbsent: aBlock`

returns the value assigned to the key `aKey`. If the key is not found, the block `aBlock` is evaluated.

`associationAt: aKey`

returns the association whose key is `aKey`. If the key is not found, an error is produced.

`associationAt: aKey ifAbsent: aBlock`

returns the association whose key is `aKey`. If the key is not found, the block `aBlock` is evaluated.

`keyAtValue: aValue`

returns a key that refers to the value `aValue`, and if several keys reference the same value, returns the first one found. If no key is found, `nil` is returned.

`keys`

returns an instance of class `Set` containing all the keys of the receiver,

`values`

returns an instance of class `Bag` containing all the values of the receiver.

For example:

`dictionary <- Dictionary new.`

`dictionary at: #un put: #one.`

`dictionary at: #deux put: #two.`

`dictionary at: #trois put: #three.`

`dictionary add: (Association key: #quatre value: #four).`

allows a dictionary to be created. We have used two messages to add an element to the dictionary, the message `at:put:` and the message `add:` whose argument must be an `Association`.

<table><thead><tr><td>Expressions</td><td>Result</td></tr></thead><tbody><tr><td>dictionary at: #deux</td><td>two</td></tr><tr><td>dictionary associationAt: #deux</td><td>deux -> two</td></tr><tr><td>dictionary keyAtValue: #three</td><td>trois</td></tr><tr><td>dictionary keys</td><td>Set (un deux trois quatre)</td></tr><tr><td>dictionary values</td><td>Bag (one two three four)</td></tr></tbody></table>

### Test

Being a subclass of `Collection`, the class `Dictionary` inherits the test messages of this class, in particular, `includes:`, although the method assigned to this message is redefined in the class `Dictionary`. This message allows for testing the inclusion or otherwise of a value of an association. The same goes for the message `occurrencesOf:`. The new messages are:

`includesAssociation: anAssociation`
returns true if the receiver contains the element an-Association,

includesKey: aKey

returns true if one of the elements of the receiver has aKey as its key.

For example:

<table><thead><tr><td>Expressions</td><td>Result</td></tr></thead><tbody><tr><td>dictionary includes: #two</td><td>true</td></tr><tr><td>dictionary includes: #deux</td><td>false</td></tr><tr><td>dictionary includesAssociation: (Association key: #deux value: #two)</td><td>true</td></tr><tr><td>dictionary includesKey: #two</td><td>false</td></tr><tr><td>dictionary includesKey: #deux</td><td>true</td></tr></tbody></table>

## Deletion

Three new messages allow an element to be deleted from a dictionary. The message remove: defined in Collection is unusable for a dictionary. So as to be able not to use it, the method assigned to it is redefined in Dictionary; it is written as follows:

remove: anObject

self shouldNotImplement

The new messages are:

removeAssociation: anAssociation

which deletes the element anAssociation from the receiver. If the element anAssociation is not found in the receiver, an error is produced.

removeKey: aKey

deletes the element of the receiver whose key is aKey. If the key is not found, an error is produced; if successful, the value assigned to the key is returned.

For example:

<table><thead><tr><td>Expressions</td><td>Dictionary</td></tr></thead><tbody><tr><td>dictionary removeAssociation: (Association key: #un value: #one)</td><td>Dictionary (deux -> two, quatre -> four, trois -> three)</td></tr><tr><td>dictionary removeKey: #deux</td><td>Dictionary (trois -> three, quatre -> four)</td></tr></tbody></table>

## Enumeration

Being a subclass of class Collection, class Dictionary inherits the messages of this class, in particular, `do:`, even though the method assigned to this class is redefined in class Dictionary. This message allows evaluation of a block for all values of the receiver and not the associations. The new messages are:

associationsDo: aBlock
evaluates the block aBlock for all associations of the receiver.

keysDo: aBlock

evaluates the block aBlock for all keys of the receiver.

For example:

dictionary associationDo: [:anAssociation | anAssociation
value:anAssociation value asString]

means that the values of the dictionary are no longer
symbols but strings. The result for the dictionary is:
Dictionary (one -> 'un' two -> 'deux' three -> 'trois'
four -> 'quatre').

### 11.6.4 The class IdentityDictionary

The class IdentityDictionary is a subclass of class
Dictionary. The difference between these two classes is
that for class Dictionary the search for a key uses the
equality (=), whereas for class IdentityDictionary the
search for a key uses the equivalence (==).

### 11.6.5 The class SequenceableCollection

The class SequenceableCollection is a subclass of class
Collection. The instances of SequenceableCollection have
ordered elements that are accessible via a numeric
index. An instance of SequenceableCollection possesses a
first element and a last element.

#### Access

Being a subclass of Collection, the class Sequenceable-
Collection inherits from the access messages of this
class, especially at: and at:put:. The other messages
are:

atAll: aCollection put: anObject

assigns the argument anObject to each index of the rec-
eiver that belongs to the argument aCollection,

atAllPut: anObject

assigns the argument anObject to all indices of the rec-
eiver,

first

returns the first element of the receiver, producing an
error if the receiver is empty,

last

returns the last element of the receiver, producing an
error if the receiver is empty,

indexOf: anElement

returns the first index of the element anElement,
returning 0 if the receiver does not contain the element
anElement,

indexOf: anElement ifAbsent: aBlock

returns the first index of the element anElement, and
evaluates the block aBlock if the receiver does not contain the element anElement,

`indexOfSubCollection: aSubCollection`

`startingAt: anIndex`

if the argument aSubCollection is a subcollection of the receiver, returns the index in the receiver of the first element of the subcollection, the search starting at the index anIndex, and returns 0 if the subcollection is not found,

`indexOfSubCollection: aSubCollection`

`anIndex ifAbsent: aBlock`

if the argument aSubCollection is a subcollection of the receiver, returns the index in the receiver of the first element of the subcollection, the search starting at the index anIndex, and evaluates the block aBlock if the subcollection is not found,

`replaceFrom: beginning to: end with: aCollection`

replaces the elements whose index lies between beginning and end with the elements of the argument aCollection; if the size of the argument aCollection does not match with beginning and end, an error is produced,

`replaceFrom: beginning to: end with: aCollection`

`startingAt: indexBeginning`

replaces the elements whose index lies between beginning and end with the elements of the argument aCollection, starting at the index indexBeginning; the size of aCollection must not be less than (end - beginning + indexBeginning). For example:

<table><thead><tr><th>Expressions</th><th>Result</th></tr></thead><tbody><tr><td>`#($a $b $c $d) size`</td><td>4</td></tr><tr><td>`#($a $b $c $d) at: 3`</td><td>$c</td></tr><tr><td>`#($a $b $c $d) at: 3 put: $e`</td><td>`#($a $b $e $d)`</td></tr><tr><td>`#($a $b $c $d) atAll: #($f $f $c $d)`</td><td>`#($f $f $c $d)`</td></tr><tr><td>`#($a $b $c $d) atAllPut: $a`</td><td>`#($a $a $a $a)`</td></tr><tr><td>`#($a $b $c $d) first`</td><td>$a</td></tr><tr><td>`#($a $b $c $d) last`</td><td>$d</td></tr><tr><td>`#($a $b $c $d) indexOf: $b`</td><td>2</td></tr><tr><td>`#($a $b $c $d) indexOf: $t ifAbsent: [5]`</td><td>5</td></tr><tr><td>`'abcdefgh' indexOfSubCollection: 'cd'`</td><td>1</td></tr><tr><td>`'abcabc' indexOfSubCollection: 'bc'`</td><td>3</td></tr><tr><td>`'abcdefgh' replaceFrom: 5 to: 7 with 'FGH'`</td><td>'abcdFGHL'</td></tr><tr><td>`'abcdefgh' replaceFrom: 5 to: 8 with: 'ABCDEEGHIJK'`</td><td>'abcdCDEF'</td></tr></tbody></table>

### Copy

There are messages that allow all or part of an instance of SequenceableCollection to be copied. They are:

`aCollection`
returns a copy of the receiver concatenated with the argument aCollection which must be an instance of SequenceableCollection,

`copyFrom:` beginning to: end

returns a copy of the subcollection of the receiver starting at the index beginning and finishing at the index end,

`copyReplaceAll:` aSubCollection with: anOtherSubCollection

returns a copy of the receiver in which all the occurrences of the subcollection aSubCollection are replaced with the collection anOtherSubCollection,

`copyReplaceFrom:` beginning to: end with: aCollection if end is greater than beginning, replaces the subcollection starting at the index beginning and finishing at the index end with the collection aCollection; if end is less than beginning, inserts the collection aCollection in front of the index beginning and returns the copy of the new collection,

`copyWith:` anObject

returns a copy of the receiver concatenated with anObject,

`copyWithout:` anObject

returns a copy of the receiver from which all occurrences of the object anObject have been removed.

For example:

<table><thead><tr><td>Expressions</td><td>Result</td></tr></thead><tbody><tr><td>'abc','def'</td><td>'abcdef'</td></tr><tr><td>'abcdef' copyFrom: 2 to: 5</td><td>'bcde'</td></tr><tr><td>'abcdef' copyReplaceAll: 'cd' with: 'CDE'</td><td>'abCDef'</td></tr><tr><td>'abcdef' copyReplaceFrom: 2 to: 3 with: 'AAA'</td><td>'aAAAdef'</td></tr><tr><td>'abcdef' copyReplaceFrom: 3 to: 2 with: 'AAA'</td><td>'abAAAcdef'</td></tr><tr><td>'abcdef' copyWith: $g</td><td>'abcdefg'</td></tr><tr><td>'abcdef' copyWithout: $f</td><td>'abcde'</td></tr></tbody></table>

## Enumeration

Because the elements of an instance of SequenceableCollection are ordered, enumeration of these elements is also made in an ordered manner. The new messages accessible by the instances of SequenceableCollection are:

`findFirst:` aBlock

which evaluates the block aBlock for each element of the receiver, and returns the index of the first element for which evaluation of the block returns true,

`findLast:` aBlock

evaluates the block aBlock for each element of the receiver, and returns the index of the last element for
which evaluation of the block returns true,

reverseDo: aBlock

evaluates the block aBlock for each element of the receiver starting with the last and going back to the first,

with: aCollection do: aBlock

evaluates the two argument block aBlock, taking as first argument an element of the receiver and as second argument an element of the SequenceableCollection aCollection. The SequenceableCollection aCollection must be the same size as the receiver.

For example:

<table><thead><tr><th>Expressions</th><th>Result</th></tr></thead><tbody><tr><td>'abcDEFG' findFirst: [:i | i isUppercase]</td><td>4</td></tr><tr><td>'abcDEFG' findLast: [:i | i isUppercase]</td><td>7</td></tr><tr><td>mult <- Bag new.</td><td></td></tr><tr><td>#{1 2 3 4} with: #{5 6 7 8}</td><td></td></tr><tr><td>do: [:i :j | mult add: i*j].</td><td></td></tr><tr><td>mult</td><td>Bag(5 12 21 32)</td></tr></tbody></table>

SequenceableCollection possesses several subclasses; these are OrderedCollection, LinkedList, Interval and ArrayedCollection.

### 11.6.5.1 The class OrderedCollection

The class OrderedCollection is a subclass of SequenceableCollection. The order of the elements of an instance of OrderedCollection is fixed by the order in which they are added. The new messages accessible by the instances of OrderedCollection are:

addLast: anObject

which adds the object anObject to the end of the receiver,

addFirst: anObject

adds the object anObject to the beginning of the receiver,

add: anObject after: anOtherObject

adds the object anObject to the receiver after the first occurrence of anOtherObject. If the object anOtherObject is not an element of the receiver, an error message is produced,

add: anObject before: anOtherObject

adds the object anObject to the receiver in front of the first occurrence of anOtherObject. If the object anOtherObject is not an element of the receiver, an error message is produced,

addAllFirst: aCollection

adds to the beginning of the receiver all the elements of the OrderedCollection aCollection,

addAllLast: aCollection
adds to the end of the receiver all the elements of the OrderedCollection aCollection,

removeFirst

removes the first element of the receiver and returns this element,

removeLast

removes the last element of the receiver and returns this element. An error is produced if the receiver is empty,

after: anObject

returns the element that appears after the first occurrence of the object anObject. If the receiver contains no object anObject or there is no element after anObject, an error is produced,

before: anObject

returns the element that appears in front of the first occurrence of the object anObject. If the receiver contains no object anObject or there is no element in front of anObject, an error is produced.

For example:

<table><thead><tr><th>Expressions</th><th>List</th></tr></thead><tbody><tr><td>list &lt;- OrderedCollection new.</td><td>OrderedCollection ()</td></tr><tr><td>list add: 1</td><td>OrderedCollection (1)</td></tr><tr><td>list addFirst: 2</td><td>OrderedCollection (2 1)</td></tr><tr><td>list addLast: 3</td><td>OrderedCollection (2 1 3)</td></tr><tr><td>list add: 4 after: 1</td><td>OrderedCollection (2 1 4 3)</td></tr><tr><td>list add: 5 before: 1</td><td>OrderedCollection (2 5 1 4 3)</td></tr><tr><td>list removeFirst</td><td>OrderedCollection (5 1 4 3)</td></tr><tr><td>list removeLast</td><td>OrderedCollection (5 1 4)</td></tr><tr><td>list before: 1</td><td>returns 5</td></tr><tr><td>list after: 1</td><td>returns 4</td></tr><tr><td>list addAllFirst: list</td><td>OrderedCollection (5 1 4 5 1 4)</td></tr><tr><td>list addAllLast: list</td><td>OrderedCollection (5 1 4 5 1 4 5 1 4)</td></tr></tbody></table>

### 11.6.5.2 The class SortedCollection

The class *SortedCollection* is a subclass of *OrderedCollection* whose elements are ordered. To order these elements the class uses a function represented by a two argument block. To create an instance of *SortedCollection*, it is sufficient to send the message *sortBlock*: to the class. The argument of *sortedBlock*: is a two argument
To create an instance of the class Link, the message
nextLink: aLink
needs to be sent to the class. The argument of the mess-
age nextLink: must be an instance of Link.

There are two messages that are understood by inst-
ances of Link:

nextLink

which returns the instance of Link referenced by the
receiver; and

nextLink: aLink

which allows the reference of the receiver to be alter-
ed.

The class Link has no direct instances because they
would not be usable (that is, the class Link is an
abstract class). To use the classLinkedIn, subclasses
of Link have to be defined whose instances will have
other usable variables.

The instances of LinkedInList understand the same mess-
ages as the instances of Link; they also understand all
the messages of the class SequenceableCollection (add-
First, removeFirst, etc). The following example, which
allows a circular list of n objects to be created, shows
how the class LinkedInList may be used:

<table><tr><td>name of class</td><td>Bond</td></tr><tr><td>superclass</td><td>Link</td></tr><tr><td>name of instance variables</td><td>object</td></tr><tr><td>instance methods</td><td></td></tr><tr><td>object</td><td></td></tr><tr><td>↑object</td><td></td></tr><tr><td>object: anObject</td><td></td></tr><tr><td>object <- anObject</td><td></td></tr><tr><td>name of class</td><td>CircularList</td></tr><tr><td>superclass</td><td>LinkedIn</td></tr><tr><td>class method</td><td></td></tr><tr><td>new: ASize</td><td></td></tr><tr><td>|aList|</td><td></td></tr><tr><td>aList <- super new.</td><td></td></tr><tr><td>(1 to: aSize) inject: nil into:</td><td>[:i :j| aList addFirst: (Bond nextLink: i)].</td></tr><tr><td>aList last nextLink: aList first</td><td></td></tr></table>

### 11.6.5.4 The class Interval

The class Interval is a subclass of SequenceableCollect-
ion whose instances represent arithmetic sequences. An
arithmetic sequence is characterised by its first ele-
ment and the increment which steps from one element to
the next up to a finite limit. There are two messages
that create Interval instances.

from: beginning to: end
returns an instance of the class Interval starting at the beginning number and finishing at the end number, with increments of 1.

from: beginning to: end by: anIncrement

returns an instance of the class Interval starting at the beginning number and finishing at the end number and incrementing by anIncrement.

The class Number also supports two messages that create Interval instances:

to: aNumber

which returns an instance of the class Interval starting at the receiver and finishing at the number aNumber, with an increment of 1.

to: aNumber by: anIncrement

which returns an instance of the class Interval starting at the receiver and finishing at the number aNumber, with an increment of anIncrement.

For example:

1 to: 5 by: 2

returns an instance of Interval whose elements are 1, 3 and 5.

1 to: 5 by: 2.1

returns an instance of Interval whose elements are 1 and 3.1.

### 11.6.5.5 The class ArrayedCollection

The class ArrayedCollection is a subclass of Sequence-ableCollection whose instances are arrays of objects. Each object is accessible by a numeric key representing its position in the array. The class ArrayedCollection, which is an abstract class, has five subclasses, as described below.

#### - The class Array

An instance of the class Array can store any type of object. The messages understood by instances of Array are the messages supported by the class Collection.

#### - The class String

In contrast to class Array the instances of class String only contain characters. The instances of String are therefore strings of characters. The additional messages supported by the class String are:

#### Creation

Two messages allow instances of String to be created:

fromString: aString

returns a copy of the string aString;

readFrom: aStreamOfCharacters

returns an instance of String created from the characters contained in the stream of characters aStreamOfCharacters (an instance of Stream, see chapter 12).
## Comparison

Six messages allow strings of characters to be compared with one another. The distinction between upper and lower case is ignored. These messages are:

`<aString`

returns true if the receiver precedes the argument aString alphabetically,

`<=aString`

returns true if the receiver precedes the argument aString alphabetically or if two strings are equal,

`>aString`

returns true if the receiver follows the argument aString alphabetically,

`>=aString`

returns true if the receiver follows the argument aString alphabetically or if the two strings are equal,

`match: aString`

returns true if the argument aString appears in the receiver. The characters # and * have a special meaning in the receiver:

- `#` can represent any character

- `*` can represent any string of characters (including the empty string).

`sameAs: aString`

returns true if the receiver and the argument aString are equal.

## Conversion

Three messages allow character strings to be converted:

`asLowerCase`

returns a string of characters equivalent to the receiver containing only lower case characters,

`asUpperCase`

returns a string of characters equivalent to the receiver containing only upper case characters,

`asSymbol`

returns the symbol made up of characters of the receiver.

For example:

<table><thead><tr><td>Expressions</td><td>Result</td></tr></thead><tbody><tr><td>'String' = 'String'</td><td>true</td></tr><tr><td>'String' = 'string'</td><td>false</td></tr><tr><td>'String' sameAs: 'String'</td><td>true</td></tr><tr><td>'String' sameAs: 'string'</td><td>true</td></tr><tr><td>'#string' match: 'string'</td><td>true</td></tr><tr><td>'*ng' match: 'string'</td><td>true</td></tr><tr><td>'string' asUpperCase</td><td>'STRING'</td></tr><tr><td>'string' asSymbol</td><td>string</td></tr></tbody></table>
### The class Symbol

The class `Symbol` is a subclass of the class `String` whose instances are used to name objects in the system. The objects that have to be named are for example classes, messages, variables, etc. In the interests of saving space, symbols are only represented once in the system. Two messages allow new symbols to be created:

`intern`: `aString`

returns the unique symbol made up of the characters of the string `aString`;

`internCharacter`: `aCharacter`

returns the unique symbol made up of the character `aCharacter`.

Remember that the syntax for writing a symbol as a literal form is `#nameOfSymbol`.

### The class Text

The class `Text` is a subclass of `ArrayedCollection`. The class `Text` allows strings of characters to be stored as `String`, with the additional possibility of assigning to each character a further characteristic that can for example represent the style of the character when displayed.

### The class ByteArray

The class `ByteArray` is a subclass of the class `ArrayedCollection` whose instances contain integers coded into a byte (between 0 and 255). This class allows arrays of such integers to be stored efficiently.

### The class RunArray

The class `RunArray` is a subclass of the class `ArrayedCollection`. This class allows the convenient storage of arrays containing sequences of similar objects. The instances of `RunArray` have two named instance variables that are runs and values. The variable `runs` contains a list of integers and the variable `values` contains a list of objects. Each object of `values` is assigned to an integer of `runs` that represents the number of consecutive occurrences of this object.
## 12 The Class Stream

Collections allow objects to be grouped. Each object of a collection can be accessed individually; also, an operation can be carried out on all the objects of a collection, provided that this is done in a loop. However, it is not easy to mix the two types of access and operate on the enumeration of objects.

The class Stream is a subclass of the class Object that allows streams of objects to be controlled. The instances of Stream have a variable representing the current object in the objects stream. The instances of Stream do not directly store objects, but they do control access to these objects.

Several types of access are possible; they will be defined in the subclasses of Stream, which accounts for why Stream is an abstract class.

To summarise, the instances of Stream allow access to the collections to be controlled.

The messages of class Stream can be classified into several categories, as follows.

### Reading

Four access messages are understood by the instances of Stream:

next

returns the next object accessed by the receiver,

next: anInteger

returns the next anInteger objects accessed by the receiver, in the collection form of the same class as the collection accessible by the receiver,

nextMatchFor: anObject

accesses the next object and returns true if this object is equal to the argument anObject,

contents

returns all the objects accessed by the receiver.

### Writing

Three write messages are understood by the instances of Stream:

nextPut: anObject

stores the argument anObject at the next position accessed by the receiver and returns anObject,

nextPutAll: aCollection
stores all the objects of the argument `aCollection` at
the next positions accessed by the receiver and returns
`aCollection`,

`next: anInteger put: anObject`

stores the argument `anObject` at the next `anInteger` positions accessed by the receiver and returns `anObject`.

### Test

The message `atEnd` establishes whether the receiver can access any more objects.

### Enumeration

The message `do: aBlock` evaluates the argument `aBlock` for all the objects accessible by the receiver.

## 12.1 The class PositionableStream

The class `PositionableStream` is a subclass of `Stream`. It is again an abstract class that has three subclasses:

- the class `ReadStream`

- the class `WriteStream`

- the class `ReadWriteStream`

In addition to the protocol defined within class `Stream`, instances of the class `PositionableStream` allow positioning within the object stream; these streams of objects therefore must themselves be ordered, that is, they must be instances of the class `SequenceableCollection`.

To create an instance of `PositionableStream`, two messages are possible:

`on: aCollection`

returns an instance of `PositionableStream` allowing control of the stream made up of the objects of the argument `aCollection`.

`on: aCollection from: indexBeginning to: indexEnd` returns an instance of `PositionableStream` allowing control of the stream made up of the objects of the argument `aCollection` that lie between the arguments `indexBeginning` and `indexEnd`.

The additional messages understood by the instances of `PositionableStream` fall into several categories, as follows.

### Test

The message `empty?` returns `true` if the collection controlled by the receiver is empty.

### Access

Four messages allow access to the objects of the collection controlled by the receiver:

`peek`

returns the next object of the collection, but does not
alter the current position in the stream; it returns nil if the receiver is at the end,

peekFor: anObject

returns true and advances one position in the stream if the next object is equal to the argument anObject; if the object is not found, it returns the remainder of the collection,

reverseContents

returns a collection in inverse order of that controlled by the receiver.

## Positioning

The messages that alter or give the position in the objects stream are:

position

returns the integer representing the current position in the stream,

position: anInteger

places the receiver at the position given by the argument anInteger; if the position given as argument is not within the limits of the collection controlled by the receiver, an error is produced,

reset

places the receiver at the beginning of the collection that it controls,

setToEnd

places the receiver at the end of the collection that it controls,

skip: anInteger

shifts the current position of the argument anInteger, ensuring that this position never goes beyond the permitted bounds,

skipTo: anObject

shifts the current position to place it immediately after the next occurrence of the argument anObject in the collection controlled by the receiver; it returns true if such an object exists and false otherwise.

For example:

<table><thead><tr><td>Expression</td><td>Result</td></tr></thead><tbody><tr><td>pS &lt;- ReadStream on: # (peter paul john)</td><td></td></tr><tr><td>pS reset</td><td></td></tr><tr><td>pS next</td><td>peter</td></tr><tr><td>pS next</td><td>paul</td></tr><tr><td>pS next</td><td>john</td></tr><tr><td>pS next</td><td>nil</td></tr><tr><td>pS position</td><td>3</td></tr><tr><td>pS position: 2</td><td>2</td></tr><tr><td>pS peek</td><td>paul</td></tr><tr><td>pS next</td><td>paul</td></tr><tr><td>pS contents</td><td>(peter paul john)</td></tr><tr><td>pS reverseContents</td><td>(john paul peter)</td></tr></tbody></table>
### 12.1.1 The class ReadStream

The class `ReadStream` is a subclass of the class `PositionableStream`. The instances of this class can read the stream of objects of a collection but cannot alter this stream. None of the messages `nextPut()`, `next:` and `next-PutAll:` is recognised.

### 12.1.2 The class WriteStream

The class `WriteStream` is a subclass of the class `PositionableStream`. The instances can alter the objects stream of a collection but cannot read the objects of this stream. In the system this class is used on numerous occasions to implement the methods `printString` and `printOn` that allow objects to be displayed in a textual form.

Additional messages are supported by the class `WriteStream`. They fall into the following categories.

#### Creation

The messages that allow instances to be created are:

`with: aCollection`

creates an instance of `WriteStream` allowing the collection given as argument to be controlled, and places it at the end of the stream (the next objects will be added at the end),

`with: aCollection from: indexBeginning to: indexEnd` creates an instance of `WriteStream` allowing control of the collection of objects lying between the arguments `indexBeginning` and `indexEnd` in the collection given as argument, and places it at the end of the stream (the next objects will be added at the end).

#### Writing characters

The following methods allow a character to be added to an objects stream:

`cr`

adds a carriage-return after the current position of the receiver,

`tab`

adds a tabulation after the current position of the receiver,

`space`

adds a space after the current position of the receiver,

`crTab`

adds a carriage-return and a tabulation after the current position of the receiver,

`crTab: n`

adds a carriage-return and tabulations after the current position of the receiver.

An interesting case is where the collection is a string of characters. In such a case the control of the character stream amounts to carrying out editing funct-
ions on a string of characters.

### 12.1.3 The class ReadWriteStream

The class `ReadWriteStream` is a subclass of `WriteStream` which allows control of a stream of objects when reading or writing. It supports all the messages of `ReadStream` and `WriteStream`.

## 12.2 The class ExternalStream

The class `ExternalStream` is a subclass of the class `ReadWriteStream`. In the Smalltalk system, communication with the external files is also carried out by means of data streams. In contrast to the subclasses of `Stream` that we have already met, the input/output streams do not contain any objects but only bytes. The messages supported by the class `ExternalStream` fall into two categories.

### Access

The access messages to byte streams are:

`nextNumber: n`

returns the next *n* bytes of the collection accessed by the receiver and interprets them as a positive instance of `SmallInteger` or of `LargePositiveInteger`, depending on the value read,

`nextNumber: n put: anInteger`

stores in *n* bytes the positive integer `anInteger` (an instance of `SmallInteger` or of `LargePositiveInteger`) in the collection accessed by the receiver,

`nextString`

returns in the form of a character string (instance of `String`) the next bytes of the collection accessed by the receiver,

`nextStringPut: aString`

stores the string of characters `aString` in the form of bytes in the collection accessed by the receiver,

`nextWord`

returns the next two bytes interpreted as an integer,

`nextWordPut: anInteger`

stores in two bytes the integer `anInteger` in the collection accessed by the receiver.

### Positioning

The messages for positioning on the byte streams are:

`padTo: aSize`

places itself at the next multiple position of `aSize`, and returns the number of bytes skipped,

`padTo: aSize put: aCharacter`

places itself at the next multiple position of `aSize` writing the character `aCharacter` the required number of
times, and returns the number of bytes skipped,

padToNextWord

places itself on the next word (first even byte position), and returns the character skipped if there is one,

padToNextWordPut: aCharacter

places itself on the next word writing the character
aCharacter as many times as necessary,

skipWords: n

skips n words,

wordPosition

returns the current position in words,

wordPosition: aPosition

places itself at the position aPosition in words.

### 12.2.1 The classinde Stream

The class **FinancialStream** is a subclass of the abstract class **ExternalStream**. All accesses to files are carried out by means of instances of **FinancialStream**. In contrast to its superclasses, the class **FinancialStream** does not work on collections present in central memory, but on streams of bytes present in auxiliary memories. In addition to the messages supported by the class **ExternalStream**, the class **FinancialStream** supports messages relating to the status of a file (open, closed, etc). Three class methods allow instances of **FinancialStream** to be created:

oldFileNamed: aString

creates an instance of **FinancialStream** accessing the file
named aString and verifies that it exists,

newFileNamed: aString

creates an instance of **FinancialStream** accessing the file
named aString, creating it if it does not exist and de-
leting it if it does,

fileNamed: aString

creates an instance of **FinancialStream** accessing the file
named aString and creating it if it does not exist.

The two important new messages supported by **File-**
**Stream** are:

open

which allows the file accessed by the receiver to be
opened; read and write operations cannot take place
until this message has been sent.

close

which allows the file accessed by the receiver to be
closed.

### 12.2.2 The classFileDirectory

The class **FileDirectory** is a subclass of the class **File-Stream**. The class **FinancialStream** allows files to be named, while the class **FileDirectory** allows them to be located in the logical organisation of the secondary memory. The
methods of the class FileDirectory depend on the system support, that is, the file organisation of the operating system on which the Smalltalk interpreter has been written. The instances of the class FileDirectory represent directories or volumes.
# 13 Processes

A process represents a sequence of instructions that has to execute a particular task. A conventional machine, for example, contains processes for reading the keyboard, writing to disk, printing out text via a printer, etc. When a machine is what is known as a uniprocessor, it can only execute one process at a time; it is therefore necessary to be able to select a process to execute and synchronise the various processes required. Smalltalk-80 contains several classes that allow such concepts to be defined.

## 13.1 The class Process

A process is a sequence of expressions that are interpreted by Smalltalk. There are already in the system processes that inspect the input interfaces (keyboard and mouse) and a process that is activated when the amount of available memory is running low, notifying the user of a potential problem.

Processes are instances of the class Process which is a subclass of Link. To create a new process, four messages are supported by the class BlockContext:

**fork**

creates a new process from the receiver which is a block containing the expressions to be interpreted, and places it on the list of processes to be executed; the priority of the process created is equal to the priority of the process that creates it,

**forkAt: aPriority**

creates a new process from the receiver which is a block containing the expressions to be interpreted, and places it on the list of processes to be executed with the priority `aPriority`,

**newProcess**

creates a new process from the receiver which is a block containing the expressions to be interpreted, but does not place it on the list of processes to be executed,

**newProcessWith: anArray**

creates a new process from the receiver which is a block containing the expressions to be interpreted, without
putting it on the list of processes to be executed. The arguments of the block are initialised by the objects contained in the argument anArray.

The messages that allow action on processes are:

resume

which authorises execution of the receiver,

suspend

which halts executions of the receiver, but keeps it on the list of processes to be executed; to authorise continuation, the message resume must be sent,

terminate

halts execution of the receiver and removes it from the list of processes to be executed,

priority

returns the priority of the receiver,

priority: aPriority

alters the priority of the receiver and gives the value of the argument aPriority.

## 13.2 The class ProcessorScheduler

The Smalltalk virtual machine has only one processor; since as a consequence only one process can be executed at a time, the activation of the various processes must be controlled.

It is the role of the class ProcessorScheduler, a subclass of the class Object, to control a list of processes. The class ProcessorScheduler has only one instance which is stored in a global variable called Processor.

The messages supported by the class ProcessorScheduler are:

activePriority

returns the priority of the process currently being executed,

activeProcess

returns the process (instance of Process) currently being executed,

terminateActive

terminates the process currently being executed,

yield

authorises execution of a process of the same priority as the active process,

highIOPriority

returns the priority of the fast input/output processes,

lowIOPriority

returns the priority of the slow input/output processes,

systemBackgroundPriority

returns the priority of the Smalltalk processes operating in the "background",

timingPriority
returns the priority of the processes that consult the real-time clock,

`userBackgroundPriority`

returns the priority of the user processes operating in the "background",

`userInterruptPriority`

returns the priority of the user processes considered to be of high priority,

`userSchedulingPriority`

returns the priority of the non-priority user processes.

The list below gives the rank order of priorities, from the highest to the lowest:

`timingPriority` -> Priority 8

`highIOPriority` -> Priority 7

`lowIOPriority` -> Priority 6

`userInterruptPriority` -> Priority 5

`userSchedulingPriority` -> Priority 4

`userBackgroundPriority` -> Priority 3

`systemBackgroundPriority` -> Priority 2

### 13.3 The class Delay

The class Delay is a subclass of the class Object. The instances of the class Delay allow the active process to be suspended for a determined period. There are three messages to create instances of Delay, as follow.

`forMilliseconds: aNumberOfMilliseconds`

returns a new instance of the class Delay that will suspend execution of the active process for the number of milliseconds equal to the argument,

`forSeconds: aNumberOfSeconds`

returns a new instance of the class Delay that will suspend execution of the active process for the number of seconds equal to the argument,

`untilMilliseconds: aNumberOfMilliseconds`

returns a new instance of the class Delay that will suspend execution of the active process until the real-time clock reaches the value of the argument.

To suspend execution of the active process, the message `wait` must be sent to an instance of Delay that is initialised for the required delay.

The message `resumptionTime` sent to an instance of Delay returns the value in milliseconds of the real-time clock at which the interrupted process can resume.

For example:

`[[true] whileTrue:`

`[Time now printString asDisplayText displayAt:`

`Sensor cursorPoint. (Delay forSeconds: 1) wait]] fork`

will display the current time every second at the cursor position.
## 13.4 Semaphores

We have seen that processes are independent of one another. In some circumstances it is useful to be able to synchronise processes and communicate data between them.

The instances of the class **Semaphore**, which is a subclass of the class **LinkedList**, allow processes to be synchronised.

To allow a process to wait for an event from another process, it places itself in a wait state by sending a wait message to a semaphore. When the second process sends a signal to the first, the latter is able to resume.

The order in which these messages are sent has no effect on the execution of the processes, except that it may or may not cause the process placed in signal `await` state to wait.

The two messages that are involved are:

**wait**

which suspends the active process until the semaphore receives a signal,

**signal**

which allows a process to signal an event to the semaphore.

Several processes can wait for a semaphore; they resume execution in the same order that they were suspended as and when the semaphore receives the messages signalling an event.

One of the useful applications of semaphores is for achieving mutual exclusion between two processes. Two processes are in mutual exclusion when one of them cannot interrupt the other when it is in a critical section.

To define a mutual exclusion semaphore, a new semaphore must be created and the signal message sent to it. This is done by:

**forMutualExclusion**

A critical section is a part of a process that cannot be interrupted by another process. To define it, there must be a mutual exclusion semaphore to which the message wait is sent; that is, from that moment any process that sends the message wait to that same semaphore is blocked. When a critical section is terminated, it is then sufficient to signal to the semaphore to free access to the protected resource. The following message defines a critical section in a method:

**critical: aBlock**

which evaluates the argument `aBlock`, while preventing any other process from being activated.
## The class SharedQueue

The instances of this class are queues that are used in Smalltalk to transmit data between processes while protecting their integrity. The instances of this class have two instance variables that refer to two semaphores. The first counts the elements in the queue and blocks the process that reads this queue when it is empty. The second is used for read and write operations to protect the queue (two processes cannot alter the queue at the same time, because of the danger of losing data).

The messages understood by a queue are:

empty

returns true if the queue is empty, false if otherwise,

next

returns the next object in the queue and positions itself at the following object; if there is no object in the queue, the process is suspended until an object is added,

peek

returns the next object in the queue without positioning itself at the following object; if there is no object in the queue, the process is suspended until an object is added,

nextPut: anObject

places the argument anObject at the next position in the queue.

nextPut

returns the next object in the queue without positioning itself at the following object; if there is no object in the queue, the process is suspended until an object is added,

anObject

places the argument anObject at the next position in the queue.

nextPut: anObject

nextPut: anObject

places the argument anObject at the next position in the queue.
# 14 The Classes Point and Rectangle

Just as we have numbers to represent scalar sizes, we also need objects to represent sizes in two dimensions. These sizes are essential in order to represent screen positions. The class Point, a subclass of the class Object, was introduced for this purpose.

## 14.1 The class Point

The instances of the class Point have two instance variables called x and y, which represent respectively the abscissa and ordinate of a point.

### 14.1.1 Creating a point

A class method creates new points:

x: anAbscissa y: anOrdinate

returns a new instance of the class Point whose abscissa is anAbscissa and ordinate anOrdinate.

There is another instance method of the class Number that allows new points to be created:

@aNumber

returns a new instance of the class Point whose abscissa is the receiver and whose ordinate is aNumber.

### 14.1.2 Messages supported by the class Point

Like numbers (instances of the class Number), points are basic objects and therefore they understand a large number of messages. These can be divided into the following categories.

#### Access

The messages that allow access to the characteristics of a point are:

x

returns the abscissa of the receiver,

y

returns the ordinate of the receiver,

x: aNumber

replaces the abscissa of the receiver by the argument aNumber,

y: aNumber

replaces the ordinate of the receiver by the argument aNumber.
## Arithmetic

The arithmetic operations are:

**+ anOffset**

returns a new point whose x-coordinate is the sum of the x-coordinates of the receiver and the argument anOffset; similarly for the y-coordinate. If the offset is not a point but a number, the two coordinates are incremented by the same value,

**- anOffset**

returns a new point obtained by subtracting from each coordinate of the receiver the corresponding coordinate of the argument anOffset; if the offset is not a point but a number, the two coordinates are decremented by the same value,

**\* aCoefficient**

returns a new point obtained by multiplying each coordinate of the receiver by the argument aCoefficient; if the coefficient is not a point but a number, the two coordinates are multiplied by the same value,

**/ aCoefficient**

returns a new point obtained by dividing the receiver by the argument aCoefficient; if the coefficient is not a point but a number, the two coordinates are divided by the same value,

**// aCoefficient**

returns a new point obtained by carrying out the integer division for each coordinate between the receiver and the argument aCoefficient; if the coefficient is not a point but a number, the two coordinates are divided by the same value,

**abs**

returns a new point obtained by taking the absolute value of each coordinate of the receiver,

**rounded**

returns a new point whose coordinates are the integers closest to each coordinate of the receiver,

**truncateTo: aCoefficient**

returns a new point whose coordinates are the largest multiples of the argument aCoefficient smaller than the coordinates of the receiver,

**dist: aPoint**

returns the Euclidean distance between the receiver and the argument aPoint,

**grid: aPoint**

returns the multiple of the argument aPoint closest to the receiver,

**truncateGrid: aPoint**

returns the largest multiple of the argument aPoint smaller than the receiver,

**transpose**
returns a new point whose x-coordinate is the receiver's y-coordinate, and whose y-coordinate is the receiver's x-coordinate.

## Comparison

The messages that allow two points to be compared are:

`< aPoint`

returns true if the two coordinates of the receiver are less than the two coordinates of the argument,

`<= aPoint`

returns true if the two coordinates of the receiver are less than or equal to the two coordinates of the argument,

`> aPoint`

returns true if the two coordinates of the receiver are greater than the two coordinates of the argument,

`>= aPoint`

returns true if the two coordinates of the receiver are greater than or equal to the two coordinates of the argument.

For example:

<table><thead><tr><th>Expressions</th><th>Results</th></tr></thead><tbody><tr><td>Point x: 10 y: 20</td><td>10@20</td></tr><tr><td>10@20</td><td>10@20</td></tr><tr><td>(10@20)x</td><td>10</td></tr><tr><td>(19@20)y</td><td>20</td></tr><tr><td>(10@20)x: 30</td><td>30@20</td></tr><tr><td>(10@20)y: 30</td><td>10@30</td></tr><tr><td>(10@20)+(5@8)</td><td>15@28</td></tr><tr><td>(10@20)+5</td><td>15@25</td></tr><tr><td>(10@20)-(5@8)</td><td>5@12</td></tr><tr><td>(19@20)-5</td><td>14@15</td></tr><tr><td>(10@20)*(2@3)</td><td>20@60</td></tr><tr><td>(10@20)*2</td><td>20@40</td></tr><tr><td>(10@20)/(2@4)</td><td>5@5</td></tr><tr><td>(10@20)/3</td><td>(10/3)@(20/3)</td></tr><tr><td>(10@20)//(3@7)</td><td>3@2</td></tr><tr><td>(10@20)//3</td><td>3@6</td></tr><tr><td>(-10@20) abs</td><td>10@20</td></tr><tr><td>(10.7@20.2) rounded</td><td>11@20</td></tr><tr><td>(10@20) truncateTo: 3</td><td>9@18</td></tr><tr><td>(4@4) dist: (1@0)</td><td>5</td></tr><tr><td>(10@20) grid: (3.3@7)</td><td>9.9@21</td></tr><tr><td>(10@20) truncatedGrid: (3.3@7)</td><td>9.9@14</td></tr><tr><td>(10@20) transpose</td><td>20@10</td></tr></tbody></table>

## 14.2 Coordinate system within Smalltalk environment

Each point on the screen can be defined by two coordinates, an abscissa and an ordinate. The diagram
below shows the position and orientation of the two co-ordinate axes in the Smalltalk system.

<figure><img src="image_15.png" /></figure>

## 14.3 The class Rectangle

A rectangle parallel to the axes can be defined by two points. In the Smalltalk system many objects use this concept of a rectangle (for example, windows, menus, etc). The class Rectangle, which is a subclass of the class Object, allows rectangles to be defined by two points, an origin and a corner.

The origin and the corner of a rectangle are defined as shown in the following diagram:

Origin (10.10)

<figure><img src="image_16.png" /></figure>

Corner (100.50)
### 14.3.1 Creating a rectangle

Three messages create new rectangles:

origin: anOriginPoint corner: aCornerPoint
returns a new instance of the class Rectangle whose origin is anOriginPoint and corner aCornerPoint,

origin: anOrigin extent: aVector
returns a new instance of the class Rectangle whose origin is anOriginPoint and whose corner is obtained by adding to the argument anOrigin the argument aVector (which is an instance of Point),

left: limitLeft right: limitRight top: limitTop

bottom: limitBottom

returns a new instance of the class Rectangle whose coordinates are delimited by the limits given as arguments.

There are two messages understood by instances of the class Point that also allow new rectangles to be created:

extent: aPoint

returns a new instance of the class Rectangle whose origin is given by the receiver and whose corner is obtained by adding the origin to the argument aPoint,

corner: aPoint

returns a new instance of the class Rectangle whose origin is given by the receiver and whose corner is the argument aPoint.

### 14.3.2 Instance methods

The instance methods of the class Rectangle may be divided into several categories:

#### Access

There are nine methods for accessing particular points of a rectangle:

topLeft

returns the point located at the top left of the receiver,

topCenter

returns the point located at the top centre of the receiver,

topRight

returns the point located at the top right of the receiver,

leftCenter

returns the point located at the left centre of the receiver,

center

returns the point located at the centre of the receiver,

rightCenter
returns the point located at the right centre of the
receiver,
bottomLeft

returns the point located at the bottom left of the receiver,
bottomCenter

returns the point located at the bottom centre of the
receiver,
bottomRight

returns the point located at the bottom right of the
receiver,
origin

returns the same point as the method topLeft,
corner

returns the same point as the method bottomRight.

These points are located as shown in the following
diagram:

<figure><img src="image_17.png" /></figure>

Other messages give access to the characteristics of
the receiver:

origin: anOrigin corner: aCorner

replaces the origin and the corner of the receiver by
the arguments anOrigin and aCorner,

origin: anOrigin extent: aSize

replaces the origin by the argument anOrigin and the
corner by the point obtained by adding the origin with
the argument aSize,

width

returns the width of the receiver,
height

returns the height of the receiver,
extent

returns aPoint whose abscissa is the width and whose
ordinate is the height,
top
returns the ordinate of the origin of the receiver,
bottom

returns the ordinate of the corner of the receiver,
left

returns the abscissa of the origin,
right

returns the abscissa of the corner,
area

returns the area of the rectangle (the product of its
height and its width).

## Operations on rectangles

These operations return new objects, in contrast to
those that we shall examine later, which transform the
receiver. These operations are:

amountToTranslateWithin: aRectangle

returns a point corresponding to the minimal translation
that is required to be made to the receiver for it to be
placed within the argument aRectangle,

areasOutside: aRectangle

returns a collection of rectangles contained in the rec-
eiver and not intersecting the argument aRectangle,

expandBy: anIncrement

returns a new rectangle obtained by increasing the rec-
eiver by the value given as argument; the argument can
be a number, a point or a rectangle,

insetBy: aDecrement

returns a new rectangle obtained by decreasing the rec-
eiver by the value given as argument; the argument can
be a number, a point or a rectangle,

insetOriginBy: anOriginIncrement

cornerBy: aCornerDecrement

returns a new rectangle whose origin is the origin of
the receiver increased by the argument anOriginIncre-
ment and whose corner is the corner of the receiver de-
creased by the argument aCornerDecrement; the arguments
can be points or numbers,

intersect: aRectangle

returns the rectangle obtained by taking the intersec-
tion of the receiver and the argument,

merge: aRectangle

returns the smallest rectangle containing the receiver
and the argument,

rounded

returns a new rectangle whose coordinates are the
rounded coordinates of the receiver,

translateBy: aTranslation

returns a new rectangle whose coordinates are the co-
ordinates of the receiver translated from the argument
aTranslation; aTranslation can be a number or a point,

scaleBy: aCoefficient
returns a new rectangle whose coordinates are the co-ordinates of the receiver multiplied by the argument aCoefficient; aCoefficient can be a number or a point.

## Test

Three methods allow the characteristics of a rectangle to be tested:

* contains: aRectangle

returns true if the argument aRectangle is within the receiver,

* containsPoint: aPoint

returns true if the argument aPoint is within the receiver,

* intersects: aRectangle

returns true if the intersection of the receiver and the argument aRectangle is non-empty.

## Transformations

The methods that alter rectangles are:

* moveBy: aTranslation

translates the origin and the corner of the receiver by the argument aTranslation; aTranslation can be a number or a point,

* moveto: aPoint

translates the receiver in such a way that the origin of the receiver is located at the argument aPoint.

We shall take as an example three rectangles placed as in the following diagram:

<figure><img src="image_18.png" /></figure>
<table><thead><tr><th>Expression</th><th>Result</th></tr></thead><tbody><tr><td>r1 <- Rectangle origin: (0@0) corner: (70@50)</td><td></td></tr><tr><td>r2 <- Rectangle origin: (40@30) extent: (90@50)</td><td></td></tr><tr><td>r3 <- 30@90 corner: (130@150)</td><td></td></tr><tr><td>r1 centre</td><td>35@25</td></tr><tr><td>r2 width</td><td>90</td></tr><tr><td>r3 area</td><td>6000</td></tr><tr><td>r1 amountToTranslateWithin: r3</td><td>30@90</td></tr><tr><td>r1 areasOutside: r2</td><td>OrderedCollection<br/>(0@0 corner: 70@30)<br/>(0@0 corner: 40@50))</td></tr><tr><td>r3 expandBy: 20</td><td>10@70 corner: 150@170</td></tr><tr><td>r3 expandBy: 20@10</td><td>10@80 corner: 150@160</td></tr><tr><td>r3 expandBy: (20@10 corner:<br/>10@5)</td><td>10@80 corner: 140@155</td></tr><tr><td>r1 intersect: r2</td><td>40@30 corner: 70@50</td></tr><tr><td>r1 merge: r3</td><td>0@0 corner: 130@150</td></tr><tr><td>r1 contains: r2</td><td>false</td></tr><tr><td>r1 intersects: r2</td><td>true</td></tr><tr><td>r3 containsPoint: 50@100</td><td>true</td></tr><tr><td>r1 moveBy: 10@20</td><td>10@20 corner: 80@70</td></tr><tr><td>r1 moveto: 100@100</td><td>100@100 corner: 170@150</td></tr><tr><td>r1 scaleBy: 2</td><td>200@200 corner: 340@300</td></tr><tr><td>r1 scaleBy: 2@4</td><td>200@400 corner: 340@600</td></tr><tr><td>r1 translateBy: -50</td><td>50@50 corner: 120@100</td></tr><tr><td>r1 translateBy: -50@50</td><td>50@150 corner: 120@200</td></tr></tbody></table>
# 15 The Graphics Classes

An object can be represented in different ways. For example, a collection of numbers may be seen as

- a sequence of numbers

- a histogram

- a piechart

- a curve passing through points

a rectangle may be seen as

- two points giving the extremities of the rectangle

- four right-angled segments

- a system of four mathematical equations.

We have seen that all the objects of the Smalltalk system respond to the message `printString` by returning a string of characters. This string allows the characteristics of the object to be explained, that is, its class and its instance variables. For certain objects, this representation is not helpful; they require graphic representation in addition.

In the Smalltalk system, the graphics interface consists of a bit-mapped screen. A bit-map screen is a screen in which each point is individually accessible, and where the characteristics of each point are stored in memory. A point on the screen is called a pixel, and in the case of Smalltalk each pixel can have one of two possible states, on or off. Thus, a single bit is sufficient to store this state and there are as many bits in memory as there are pixels on the screen.

## 15.1 The class Bitmap

The class **Bitmap** is a subclass of the abstract class **ArrayedCollection**. It therefore has indexed instance variables, each of which allows a machine word to be stored. The instances of the class **Bitmap** are able to store sequences of pixels. Since the size of one of these instance variables is the same as that of the machine word, pixel manipulation is carried out efficiently.

## 15.2 The class DisplayObject

The class **DisplayObject** is an abstract subclass of the class **Object**. An instance of the class **DisplayObject** represents a picture described by its width, its height,
and a point that provides the offset applied when it is displayed. The class DisplayObject contains five subclasses, each of which adopts a different way of storing a graphics object. The methods supported by the class DisplayObject are:

width

returns the width of the minimum rectangle containing the receiver,

height

returns the height of the minimum rectangle containing the receiver,

extent

returns a point whose coordinates are the width and height of the minimum rectangle containing the receiver,

offset

returns the point giving the offset of the minimum bounding rectangle when the receiver is displayed,

offset: anOffset

replaces the offset of the receiver by the argument anOffset,

scaleBy: aPoint

multiplies the offset of the receiver by the argument aPoint, coordinate by coordinate,

translateBy: aPoint

adds the argument aPoint to the offset of the receiver,

align: aPointOfAlignment with: anOtherPoint

translates the offset of the receiver such that the argument aPointOfAlignment is placed at the position of the argument anOtherPoint,

boundingBox

returns the minimum rectangle containing the receiver, taking the offset into account,

display

displays the receiver at the point 0@0,

displayAt: aPoint

displays the receiver at the point aPoint.

### 15.2.1 The class DisplayText

The class DisplayText is a subclass of the abstract class DisplayObject. The objects that we want to represent in the class DisplayText are instances of the class Text. Recall that a text is made up of a string of characters and of an instance of the class RunArray representing the style of the characters. To display a text, additional data is required, like for example the graphical representation of the character fonts or what action is to occur in the case of tabulation. Such information is collected together in the class Text-Style, each instance of which represents a style of display.
### 15.2.1.1 Creating an instance of the class DisplayText

The message asDisplayText, when sent to an instance of the class String or to an instance of the class Text, returns a new instance of the class DisplayText initialised with the character string or the text. For example:

> Time now printString asDisplayText displayAt: 100@100 displays the current time at position 100@100.

Two other messages sent to the class DisplayText allow instances to be created:

> text: aText

> returns an instance of the class DisplayText consisting of the text given as argument; the style of the instance is given by a shared variable (pool variable) placed in the dictionary TextConstants and called DefaultTextStyle (recall that the dictionaries containing the pool variables are referenced by global variables).

> text: aText textStyle: aStyle

> returns an instance of the class DisplayText consisting of the text given as argument with a style the argument aStyle.

### 15.2.1.2 Instance methods

The instance methods of the class DisplayText are:

> string

> returns the character string that makes up the text of the receiver,

> text

> returns the text of the receiver,

> text: aText

> replaces the text of the receiver by the argument aText,

> setText: aText textStyle: aStyle offset: anOffset

> replaces the text, style and offset of the receiver by the values given as argument,

> textStyle

> returns the style of the receiver,

> textStyle: aStyle

> replaces the style of the receiver by the argument aStyle.

## 15.2.2 The class DisplayMedium

The abstract class DisplayMedium is another subclass of the class DisplayObject. The graphics object is stored in pixel form. The class DisplayMedium implements additional messages that allow a drawing to be filled with a motif and a border added to the rectangle containing the drawing. A motif is a 16 x 16 pixel drawing that is repeated in every direction. The messages can be divided into categories, as follows.
### 15.2.2.1 Background colour

The messages that fill a drawing with a motif are:

black

fills the receiver with black,

black: aRectangle

fills the intersection between the argument aRectangle
and the rectangle containing the receiver with black,

darkGrey

fills the receiver with dark grey,

darkGrey: aRectangle

fills the intersection between the argument aRectangle
and the rectangle containing the receiver with dark
grey,

lightGrey

fills the receiver with light grey,

lightGrey: aRectangle

fills the intersection between the argument aRectangle
and the rectangle containing the receiver with light
grey,

veryLightGrey

fills the receiver with very light grey,

veryLightGrey: aRectangle

fills the intersection between the argument aRectangle
and the rectangle containing the receiver with very
light grey,

white

fills the receiver with white,

white: aRectangle

fills the intersection between the argument aRectangle
and the rectangle containing the receiver with white.

### 15.2.2.2 Drawing borders

The messages that add a border to an instance of the
class DisplayMedium are:

border: aRectangle width: aWidth

draws a black border inside the rectangle aRectangle of
width aWidth,

border: aRectangle width: aWidth mask: aMotif

draws a border with the motif aMotif inside the rect-
angle aRectangle of width aWidth,

border: aRectangle widthRectangle: aRectangleInterior

mask: aMotif

constructs a rectangle from the rectangle aRectangle and
from the rectangle aRectangleInterior, in which the new
rectangle has as origin the origin of the first, plus
the origin of the second, and as corner the corner of
the first less the corner of the second. It fills the
difference between the rectangle aRectangle and the new
rectangle with the motif aMotif.
### 15.2.2.3 Filling with a motif

The aim of these messages is to compose two pictures, the first having the same size as the receiver, with background colour a motif propagated in all directions; the second being the picture of the receiver.

There are several ways of composing the two pictures. In the Smalltalk system an integer is assigned to each composition rule. There are 16 of them.

#### Composition rule

<table><tr><td>0</td><td>all the pixels are white</td></tr><tr><td>1</td><td>logical AND between the two pictures</td></tr><tr><td>2</td><td>logical AND between the first picture and the second inverted picture</td></tr><tr><td>3</td><td>the final picture is the first picture</td></tr><tr><td>4</td><td>logical AND between the first inverted picture and the second picture</td></tr><tr><td>5</td><td>the final picture is the second picture</td></tr><tr><td>6</td><td>exclusive OR between the two pictures</td></tr><tr><td>7</td><td>logical OR between the two pictures</td></tr><tr><td>8</td><td>logical AND between the two inverted pictures</td></tr><tr><td>9</td><td>exclusive OR between the first inverted picture and the second picture</td></tr><tr><td>10</td><td>the final picture is the second inverted picture</td></tr><tr><td>11</td><td>logical OR between the first picture and the second inverted picture</td></tr><tr><td>12</td><td>the final picture is the first inverted picture</td></tr><tr><td>13</td><td>logical OR between the first inverted picture and the second picture</td></tr><tr><td>14</td><td>logical OR between the two inverted pictures</td></tr><tr><td>15</td><td>all the pixels are black</td></tr></table>

The messages that allow a picture to be composed with a motif are:

fill: aRectangle mask: aMotif

fills the intersection between the argument aRectangle and the rectangle containing the receiving with the motif aMotif, applying composition rule 3,

fill: aRectangle rule: aCompositionRule mask: aMotif

fills the intersection between the argument aRectangle and the rectangle containing the receiver with the motif aMotif, applying composition rule aCompositionRule,

reverse

inverts the picture of the receiver, that is, fills the
picture of the receiver with a black motif, applying
composition rule 6 (exclusive OR),

reverse: aRectangle

inverts the intersection of the receiver and the argu-
ment aRectangle,

reverse: aRectangle mask: aMotif

fills the intersection of the receiver and the argument
aRectangle with the motif given as argument, applying
composition rule 6 (exclusive OR).

### 15.2.3 The class Form

The class Form is a subclass of the class Display-
Medium. An instance of the class Form allows a rectang-
ular picture to be stored. This picture is described by
its height, its width and the value of the pixels that
make it up. The instance variable called bits which
stores pixels is an instance of the class Bitmap.

#### 15.2.3.1 Creating a form

Six messages create and initialise a Form:

extent: aSize

returns a new instance of Form whose size is equal to
the argument aSize, and whose bitmap is not yet
initialised,

extent: aSize fromArray: anArray

returns a new instance of Form whose size is equal to
the argument aSize, and whose bitmap is initialised to
the values contained in the argument anArray,

extent: aSize fromArray: anArray offset: anOffset

returns a new instance of Form whose size is equal to
the argument aSize, and whose bitmap is initialised to
the values contained in the argument anArray and offset
is initialised by the argument anOffset (the offset is a
shift that is added when the form is displayed),

fromDisplay: aRectangle

returns a new instance of Form, created from the screen
by taking the bitmap contained in the rectangle given as
argument,

fromUser

returns a new instance of Form, created from the screen
by taking the bitmap contained in the rectangle desig-
nated by the user,

fromUser: aPoint

returns a new instance of Form, created from the screen
by taking the bitmap contained in the rectangle desig-
nated by the user; the position and size of this rect-
angle are multiples of the argument aPoint,

readFrom: aFileName

returns a new instance of Form read from the file called
aFileName.
### 15.2.3.2 Other class methods

The Smalltalk system contains a number of predefined forms used to construct motifs. The size of these forms is 16 x 16 pixels. The forms available are:

<table><tr><td>black</td><td>Returns a form in which all the pixels are black</td></tr><tr><td>darkGrey</td><td>Returns a form in which almost all the pixels are black</td></tr><tr><td>grey</td><td>Returns a form in which one pixel in two is black</td></tr><tr><td>lightGrey</td><td>Returns a form in which the number of white pixels is greater than the number of black pixels</td></tr><tr><td>veryLightGrey</td><td>Returns a form in which almost all the pixels are white</td></tr><tr><td>white</td><td>Returns a form in which all the pixels are white</td></tr></table>

Some class methods return an integer corresponding to a composition rule. These methods are:

and

returns 1 which corresponds to the logical AND between the two pictures,

over

returns 3 which corresponds to the replacement of the first picture by the second,

erase

returns 4 which corresponds to the erasure in the first picture of all the pixels that are black in the second,

reverse

returns 6 which corresponds to the exclusive OR between the two pictures,

under

returns 7 which corresponds to the logical OR between the two pictures, giving the impression that the second picture is located under the first.

### 15.2.3.3 Instance methods of the class Form

Some useful messages supported by the class Form are:

bits

returns the instance of the class Bitmap that stores the pixels,

bits: aBitmap

replaces the bitmap of the receiver by the argument aBitmap

borderWidth: aWidth

inserts a black border of width aWidth around the receiver,