Você está na página 1de 181

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/262882317

Conhecendo o Smalltalk - Todos os Detalhes da Melhor Linguagem de


Programação Orientada a Objetos

Book · January 2002

CITATIONS READS

0 2,153

2 authors:

Aldo Von Wangenheim Daniel Duarte Abdala


Federal University of Santa Catarina Universidade Federal de Uberlândia (UFU)
467 PUBLICATIONS   1,207 CITATIONS    46 PUBLICATIONS   162 CITATIONS   

SEE PROFILE SEE PROFILE

Some of the authors of this publication are also working on these related projects:

Vehicular Perception and Proprioception Based on Inertial Sensing View project

Software Process Improvement - GQS/INCoD View project

All content following this page was uploaded by Aldo Von Wangenheim on 06 June 2014.

The user has requested enhancement of the downloaded file.


ËQGLFH

6PDOOWDON&RPSOHWR
9HUVmR
5HYLVmR$OGR

Capítulo 1 Por Quê Smalltalk ? . . . . . . . . . . . . . . . . . . . . . . . . . 15
Orientação a Objetos e Smalltalk 16
O quê é este livro ? 19
Para quem é este livro ? 19
Temas abordados no livro 20

Capítulo 2 Histórico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
As origens 23
O grupo de pesquisas da Xerox em Palo Alto 24
Bytecodes e JAVA 26
Adele Goldberg e seu livro 27
Smalltalk IBM 28
Smalltalk para Linux 29
Aplicações comerciais e projetos 29

Capítulo 3 Conceitos Básicos do Ambiente . . . . . . . . . . . . . . . 31


Smalltalk e VisualWorks 31
Obtendo uma cópia do VisualWorks 33

Smalltalk Completo
Arquivos com a Documentação do Smalltalk 33 Convertendo Smalltalk para C++ 71
Manuais contidos no diretório doc 34 Help do VisualWorks 72
Instalando o VIsualWorks em sua máquina 37 Gerenciando o Arquivo de Alterações 73
Iniciando e finalizando uma seção 39 Restaurando código e instâncias após a queda do sistema 73
Os principais arquivos do sistema 43 Exercícios 75
Visual Laucher 44
Browsers 45 Capítulo 4 Conceitos Básicos da Linguagem . . . . . . . . . . . . . . 77
Procurando por uma classe ? 47
Adicionando uma nova categoria 49
Orientação a Objetos 77
Classes x instâncias 78
Adicionando um novo protocolo de métodos 50
Template para a criação de classes 50 Classes 79
Instâncias 81
Template para a criação de métodos 52
Listando os métodos 52 Mecanismo de Herança e Hierarquia de Classes 82
Expandindo a hierarquia de classes 53 Polimorfismo 83
Workspace 53 Métodos, mensagens e variáveis 84
Executando código 55 Características da Linguagem 84
Resource Finder 58 Características funcionais 85
UIPainter 59 Características léxicas 86
Canvas Tool 60 Filosofia de programação 87
Palette 61 Navegar 89
Canvas 61 Editar/Criar 89
Properties 61 Inspecionar 89
Settings & VisualWorks Settings Home 62 Objetos especiais - Literais 90
Coletando o Lixo 64 Números 91
Carregando e Salvando Código Fonte 64 SmallInteger, LargePositive-Integer e LargeNegativeInteger 91
Mecanismo de fileIn/fileOut 65 Float e Double 92
Salvando em XML ou em texto chunk 65 Fraction 93
Números em outras bases 93
Geração de Pacotes de Programa: Parcels 66
Exponen-ciação 94
Código fonte e código executável 66
Adicionando um novo parcel à sua imagem 67
Caracteres 95
Removendo um parcel 68 Strings 95
Criando seu próprio parcel 68 Booleanos 95
Alguns parcels comumente utilizados 70 O Objeto Indefinido nil 96
Código Executável 71 Símbolos 96
Criando aplicativos .exe 71 Arrays 97

4 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 5


Outros Objetos Relevantes 98 Capítulo 6 Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Object 98
Pontos 99
Variáveis em Smalltalk 131
Exercícios 100 Não-Tipagem 133
Estratégia de tipagem 134
Variáveis Privadas 135
Capítulo 5 Mensagens e Métodos . . . . . . . . . . . . . . . . . . . . . 101 Variáveis de Instância 135
Estrutura do capítulo 101 Variáveis Temporárias a Métodos e Argumentos em Métodos 137
Métodos X Mensagens 102 Variável Temporárias dentro de Blocos e Argumentos em
Mensagens Unárias 103 Blocos 139
Mensagens Binárias 103 Variáveis de Instância de Classe (Class Instance Variables) 141
Inexistência de precedência entre Operadores 107 Variáveis Compartilhadas 142
Uma mensagem é enviada ao resultado da mensagem anterior 108 Variáveis estáticas 143
Mensagens por Palavra Chave (keyword messages) 109 Nomes para variáveis 144
Encadeamento de Mensagens 110 Variáveis Especiais (self, super e thisContext) 144
Ordem de avaliação e cascateamento de mensagens 112 self 144
Usando yourself 113 super 145
thisContext 145
Precedência de Mensagens 114
Como a mensagem é executada? 115
Métodos (A definição de uma mensagem) 116 Capítulo 7 Blocos, estruturas de controle e seleção . . . . . . . . 147
Nomes para Métodos 117 Blocos 147
Métodos para Acesso a Atributos 118 Funcionamento dos blocos 148
Qual o tamanho de um método? 119 Argumentos e variáveis 148
Tipos de métodos 120 Estruturas de controle e seleção 149
Indentação para métodos 121 Laços de iteração numérica 150
O que um método retorna ? 122 Laços de repetição condicionais 151
Argumentos para métodos 124 Seleções condicionais 152
Alguns protocolos comumente utilizados 125 Iterações sobre Coleções 154
do: 154
Comentários 126
detect: 154
Métodos de Classe e Métodos de Instância 127 select: 155
Exercícios 127 reject: 155
collect: 155
Exercícios 156

6 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 7


Capítulo 8 Manipulação de arquivos e estruturas de acesso Funcionamento dos processos 188
seqüencial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Criando e Finalizando um Processo 189
Iniciando um processo 189
Introdução 157
A Escala de Prioridade 192
Streams 158
Streams poscionáveis e streams externas 158
A classe Delay 194
Parando momentaneamente a execução de um processo 194
Criando instâncias de Stream 159
Streams sobre coleções 162 Interrompendo e Forçando a Execução de Processos 195
Streams sobre strings 163 Comunicação entre processos 197
Lendo, escrevendo e posicionando uma stream 163 Filas Compartilhadas 198
Lendo 164 Semáforos 199
Escrevendo 165 Criação de processos no UNIX 202
Posicionando 165
Exercícios 202
A classe Filename e Streams sobre arquivos 166
Finalmente Abrindo os Arquivos (e também fechando) 170
Arquivos não-textuais 171 Capítulo 11 Captura e Tratamento de Exceções . . . . . . . . . . . . 205
Exercícios 173 Por Que Tratar Erros ? 205
Tipos de Erros 206
Capítulo 9 Mecanismo de Dependênica . . . . . . . . . . . . . . . . . 177 Recursos indisponíveis 206
Espera à ocorrência de eventos 207
Reação Automática a Alterações 177 Erros lógicos no código 207
Registrando-se ou Excluindo-se como Dependente 178 Mecanismo de Tratamento de Erros 208
Onde são Definidos os Métodos do Mecanismo de Sinais 210
Dependência? 180 Exception e exceções do sistema 213
Mensagens updated e Mensagens changed 180 Capiturando exceções 214
Características do mecanismo de dependência 182 Sinalizando exceções 217
Broadcast 182
Ações pós-ocorrência de uma exceção 219
expressInterestIn: for: sendBack: 183
onChangeSend: to: 183 Criando seus próprios tratadores 219
A Classe Model 184 Exercícios 221
O mecanismo de dependência e o modelo MVC 185
Exercícios 185 Capítulo 12 Superfícies gráficas, contexto gráfico e primitivas
gráficas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Capítulo 10 Processos e Semáforos . . . . . . . . . . . . . . . . . . . . . 187 Objetos Gráficos em VisualWorks 223
Executando os exemplos deste capítulo 224
Processos 187
Superfícies Gráficas 224

8 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 9


Contexto gráfico 225 Capítulo 14 Janelas de diálogo . . . . . . . . . . . . . . . . . . . . . . . . . 277
Pixmaps 227
Máscaras 227 Caixas de Diálogo no VisualWorks 277
Janelas 227 Janelas de Aviso (warn boxes) 278
Objetos Gráficos 229 Janelas de Confirmação (confirm boxes) 279
Textos 230 Janelas de Requisição (input boxes) 280
Linhas 231 Janelas de Multiplas Seleções 281
Polígonos 233
Retângulos 236
Curvas Bézier e Spline 239 Capítulo 15 Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Transformações geométricas 242 Menus em Smalltalk 283
Wrappers gráficos e wrappers de atributos gráficos 244 Menu Editor 284
Imagens 245 Criando um novo menu 284
Criando imagens 246 Reposicionando, excluindo e editando 286
Capturando imagens da tela 247 Instalando o menu como um recurso 286
Criando imagens programaticamente 247 Definindo propriedades 288
Abrindo imagens de arquivos 249 Criando um Menu Programaticamente 289
Icones 252 A classe Menu 289
Cursores 252 A classe MenuItem 291
Utilizando os cursores padrão 254 A classe MenuBuilder 293
Criando um cursor 254 Tipos de Menus 294
Exercícios 257 Barras de menu 296
Menus popUp 297
Botões de menu 297
Capítulo 13 Criando GUIs Interativamente . . . . . . . . . . . . . . . . 259
Acessando Menus 298
Criando uma GUI 259 Exercícios 299
Salvando a Janela como um Recurso 260
Reeditando uma Janela 262
Capítulo 16 O paradigma MVC (Model-View-Controller) . . . . . . 301
Propriedades 263
Formatação e Espaçamento 265 O que é MVC ? 301
Definindo Propriedades e Value Holders 269 Model 304
Hierarquia de classes 304
Controlando a Aparência da GUI 272
A classe Model 304
Widgets 272 ValueModel e suas subclasses 306
Exercícios 275 View 307
Controller 307

10 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 11


Hierarquia de classes 308 Widgets Específicos do VisualWave 344
Mecanismo de obtenção do controle 309
Convenções do mouse 310
Receita 310
Capítulo 19 Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Onde encontrar exemplos ? 311

Capítulo 17 Construindo uma Aplicação: Simulador de Redes


Neurais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Um Pouco de Teoria: Perceptrons 313
Fundamentação Matemática 315
Algoritmo do Perceptron 315
Criação da Classe NeuronioArtificial 316
Modelando uma classe abstrata 316
Criando construtores 317
Criando métodos de instância 318
Organizando protocolos de métodos 319
Criação da Classe Perceptron 320
Criação do Modelo de Domínio para a Aplicação
(ModeloPerceptron) 325
Testanto o Funcionamento 329
Criando a interface com o usuário 330
PerceptronView 330
Relembrando dependência 330
PerceptronController 333
Definindo menus 334
Comunicação 335

Capítulo 18 Criação de Aplicações para WWW . . . . . . . . . . . . 337


VisualWave e Aplicações na Web 337
Instalando e Configurando o VisualWave 338
Criando e rodando um servidor 339
Executando uma Aplicação 339
Como Escrever Aplicações Web? 341
Widgets não suportados 343

12 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 13


Capítulo 1 3RU4Xr
6PDOOWDON"

Dizer que Smalltalk é a linguagem de programação orientada a


objetos por excelência é desmerecê-la. Smalltalk inventou o conceito de
orientação a objetos e, como subproduto, o conceito de interação com o
usuário através de janelas. Paradoxalmente, apesar de Smalltalk ser a lin-
guagem mais citada como exemplo de uma linguagem de programação
revolucionária, bem concebida e elegante, ela é uma das linguagens de
programação da atualidade que mais carece de boa literatura a seu res-
peito. O objetivo deste livro é preencher esta lacuna.
A linguagem de programação Smalltalk, tal qual a conhecemos
hoje, está completando 21 anos. Do ponto de vista da velocidade com que
conceitos, idéias e mesmo grandes projetos atingem a obsolescência no
mundo das tecnologias em constante mutação da Informática, isto significa
que Smalltalk pode ser considerado uma entidade paleontológica.
Por que então dar importância a Smalltalk, quando há tantas lin-
guagens novas como JAVA e conceitos de orientação a objetos distribuí-
dos como CORBA e outras coisas no mercado ?
Há duas respostas para esta pergunta e ambas são de extrema
importância. A primeira é que Smalltalk ainda é a única linguagem de pro-

14 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Por Quê Smalltalk ?

gramação comercialmente aplicada realmente orientada a objetos, pois é adaptaram alguns dos conceitos existentes na orientação a objetos para
a única que de fato implementa de forma consistente todos os aspectos da expandir as suas capacidades. As duas linguagens sobreviventes dessa
teoria da orientação a objetos. Nós vamos ver adiante que esta afirmativa explosão-OO do final da década de 80, C++ (o “C”-orientado a objetos que
vai muito além de ter conseqüências meramente acadêmicas. Vale dizer se consolidou) e DELPHI (o PASCAL orientado a objetos que conquistou o
agora que este fato torna Smalltalk a linguagem de programação para mercado) são linguagens modulares que incorporaram alguns conceitos
ensino de computação por excelência e, de longe, a melhor linguagem de orientação a objetos. Elas não são linguagens de programação orienta-
para o primeiro contato do aluno com a arte de programar, pela forma intui- das a objetos. O objetivo desta apologia de Smalltalk é, por um lado, o de
tiva com que trata a modelagem do mundo real sob a forma de programas quebrar alguns preconceitos que existem acerca de Smalltalk ser uma lin-
de computador. guagem “de brinquedo”, por outro lado, de elevar as expectativas do usuá-
A segunda resposta é que todos os impedimentos que havia para rio, reduzidas pelas capacidades limitadas das implementações de
que Smalltalk se tornasse uma linguagem de programação amplamente orientação a objetos mais comuns do mercado.
utilizada na indústria e em softwares comerciais 20 anos atrás deixaram de Como foi dito anteriormente, Smalltalk é mais que a linguagem de
existir. Hoje em dia, um computador com muita memória, um processador programação orientada a objetos por excelência. A euforia orientada a
razoável e um monitor grande e com boa resolução gráfica viraram lugares objetos que citamos anteriormente, foi na realidade desencadeada pelo
comuns e não há mais impedimentos tecnológicos ao desenvolvimento de fato de, em 1980, o Centro de Pesquisas de Palo Alto, PARC, da XEROX
software aplicativo comercial em Smalltalk. Isto tem se traduzido em um ter anunciado e demonstrado uma linguagem orientada a objetos. Esta lin-
interesse crescente, principalmente por parte da indústria e de bancos, no guagem, produto de um projeto denominado Dynabook, chamava-se
desenvolvimento de software em Smalltalk. Este interesse vem crescendo Smalltalk. Smalltalk foi o produto de longas e minunciosas pesquisas e foi
em ritmo constante desde meados da década de 90, devido tanto à facili- desenvolvido juntamente com o próprio conceito de orientação a objetos:
dade e rapidez de modelagem de processos complexos oferecida por ambos evoluíram em conjunto. Detalhes dessa evolução estão descritos
Smalltalk, como pela sua facilidade de adaptação de programas a requisi- no Capítulo 2 deste livro. O que importa no momento, é que Smalltalk
tos em constante mutação. implementou todos os conceitos de OO, desde aspectos bastante comple-
xos até coisas básicas como modelar internamente tudo como objeto,
Orientação a Quando o paradigma de Orientação a Objetos começou a se inclusive coisas básicas como números inteiros, que também são objetos,
Objetos e popularizar, no final da década de 80, houve uma grande pressão por parte também são subclasses de uma classe abstrata Object e podem ter seu
Smalltalk do mercado para o surgimento de linguagens de programação que incor- comportamento alterado pelo usuário. Em C++ ou em Delphi, inteiro, byte,
porassem as facilidades de intuitividade de modelagem, polimorfismo, reu- float são tipos de dados e não objetos e não possuem comportamento,
tilizabilidade de código e suporte à prototipagem prometidas pelo novo mas sim operações e também não possuem objeto-pai. Em Smalltalk, a
paradigma. Nessa euforia orientada a objetos surgiram uma infinidade de superclasse de Integer é Magnitude, uma classe abstrata que imple-
linguagens de programação prometendo a “melhor orientação a objetos”. menta vários comportamentos de grandezas numéricas em geral. Em
Dentre estas, só para listar algumas, podemos citar: vários PASCAis orien- Smalltalk você não “chama uma função ou procedure”, mas realmente
tados a objetos, vários “C”s orientados a objetos, LISP orientado a objetos envia uma mensagem a um objeto.
(CLOS), MODULA orientado a objetos (OBERON) e muitos outros. Com Para citar outro exemplo, em Smalltalk o tão falado polimorfismo
poucas exceções de interesse meramente acadêmico (OBERON e não é um conceito bonito mas sem utilidade, mas realmente funciona e
EIFFEL), todas essas linguagens na realidade de uma forma ou de outra

16 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 17


Por Quê Smalltalk ?

permite a você você criar vários objetos diferentes, mas que possuem Este é um livro sobre a linguagem orientada a objetos Smalltalk, O quê é este
métodos com o mesmo nome. Estes objetos realmente vão se comportar técnicas de programação em Smalltalk, metodologia de modelagem orien- livro ?
de forma diferente dependendo para qual deles uma mensagem é envi- tada a objetos visando a geração de programas em Smalltalk e um guia de
ada. Tente fazer isto em C++. A não ser que você queira chamar a técnica programação para vários tipos de aplicações usando Smalltalk, desde apli-
de usar ponteiros para funções1 de polimorfismo, isto é completamente cações gráficas e de Inteligência Artificial até aplicações cliente-servidor
impossível. Em Smalltalk é parte integrante da boa técnica de programa- na Internet.
ção fazer uso do polimorfismo para dar flexibilidade e adaptabilidade a O livro é ao mesmo tempo um guia de referência da linguagem
seus programas. Para ilustrar, no final do Capítulo 2 deste livro nós vamos Smalltalk, onde o programador pode consultar aspectos específicos da lin-
abordar várias aplicações comerciais e científicas de Smalltalk na atuali- guagem, como também um guia de programação, onde o programador
dade e relatar uma experiência de sucesso de migração de um ambiente pode consultar técnicas de programação e formas de resolver seus proble-
de programação em mainframes para Smalltalk de uma grande empresa mas específicos, com processos, arquivos e interfaces gráficas.
européia.
Neste livro são abordadas todos os conceitos básicos da lingua-
Com o surgimento de JAVA esta constelação foi finalmente modifi- gem, como sintaxe, tipos de variáveis, tipos de métodos e mensagens e
cada. JAVA pode também ser considerada uma linguagem verdadeira- como criar uma classe de objetos.
mente orientada a objetos, apesar de manter alguns conceitos de C++,
como o fato de que existem tipos primitivos de dados que não são objetos Neste livro também abordamos as principais técnicas avançadas
e de não existir uma classe pai de todas as classes. JAVA realmente imple- de programação Smalltalk e descrevemos as bibliotecas de classes que
menta o polimorfismo e uma grande flexibilidade na utilização da memória, podem ser usadas em cada caso, mostrando exemplo de aplicação práti-
através do uso de coletores de lixo, da mesma forma que em Smalltalk. O cos.
conceito básico de construção de interfaces gráficas de usuário também
segue o paradigma MVC, criado por Smalltalk. Para tonar JAVA palatável Este livro foi concebido para ser tanto um livro para o ensino da Para quem é
ao grande número de desenvolvedores de C++, principalmente europeus, programação em Smalltalk como um livro de consulta e referência. Por este livro ?
a Sun decidiu criar a linguagem com base na sintaxe do C++. Esta escolha isso, este é tanto um livro para ser usado como livro texto em um curso de
é, na nossa opinião, o maior ponto negativo de JAVA em relação a Small- programação orientada a objetos, como também um livro para ser usado
talk: o código simples e intuitivo que se poderia ter definido para uma lin- por muito tempo como manual de referência de técnicas de programação
guagem orientada a objetos foi deixado de lado em favor de na definição orientada a objetos.
de sintaxe baseada em modelos da década de 60 usada por C++. Com o O livro foi concebido para poder ser utilizado como livro texto em
atual crescimento da bases de bibliotecas de classes para diversas aplica- uma disciplina de programação de primeiro ou segundo semestre. Pode
ções de JAVA, a vantagem de 20 anos de desenvolvimento de classes de também, acompanhado de um livro de modelagem orientada a objetos, ser
Smalltalk tem se reduzido e, para o desenvolvimento de aplicações comer- um livro texto de uma disciplina de Projeto Orientado a Objetos de um
ciais, JAVA é hoje uma opção à altura. Para o ensino de programação, segundo ou tercerio semestres.
porém, Smalltalk continua sendo a opção por excelência.
Para a alunos de primeira e segunda fases de um curso de Ciên-
cias da Computação ou Sistemas de Informação, este é um livro que vai
1. Técnica que na verdade já era usada por ANSI “C” antes de surgir o C++

18 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 19


Por Quê Smalltalk ?

servir de base para o aprendizado de programação e acompanhar as suas No Capítulo 9 abordamos a teoria e a prática de um aspecto espe-
atividades de programação por muitos anos. cífico das linguagens orientadas a objetos: a mecanismo de dependência.
Para o autodidata em programação orientada a objetos ou para Esta técnica permite que se crie objetos que reajam automaticamente a
aquele que está migrando de outra área, este livro não somente serve modificações sofridas por outros.
como tutorial de Smalltalk, pois está organizado em capítulos abordando Nos capítulos 10 e 11 abordamos as técnicas que você precisa
temas encadeados e possui listas de exercícios no final dos capítulos prin- para implementar a concorrência em Smalltalk: processos, semáforos e
cipais, mas também vai servir como manual de bom estilo de programa- controle de exceções. Smalltalk permite que se crie processos indepen-
ção. Em todos os capítulos abordamos o melhor estilo de se realizar a dentes, possibilitando a uma aplicação executar várias coisas ao mesmo
modelagem e a programação dos problemas relacionados àquele assunto. tempo. Nestes capítulos vamos tratar da teoria e prática desse assunto.
Isto não é apenas uma forma de trazermos a nossa experiência no desen- Para os programadores em Linux/Unix vamso explicar também como criar
volvimento de sitemas orientados a objetos, mas também a maneria de processos de sistema operacional, externos ao ambiente Smalltalk, e con-
mostrarmos como desenvolver bons programas. trolá-los de dentro da aplicação.
Nos capítulos 12 a 15 tratamos todos os aspectos do desenvolvi-
Temas O livro foi desenvolvido para servir tanto como livro texto para o mento de aplicações com intefaces gráficas, iniciando por superfícies gráfi-
abordados no aprendizado de Smalltalk e técnicas de orientação a objetos em Smalltalk cas, contexto gráfico e primitivas gráficas, passando pelos conceitos de
livro como também para servir como material de referência de programação e programação visual de interfaces em Smalltalk e desenvolviemnto de
de estilo durante o desenvolvimento de aplicações. Em função disso, nós menus e janelas de diálogo.
construímos o livro como uma série de tópicos encadeados, mas que após
o seu aprendizado podem ser consultados de forma direta e independente. No Capítulo 16 abordamos a teoria e técnicas de programação do
paradigma MVC. O paradigma model-view-controller é o mecanismo que
No Capítulo 2 é feito um breve relato da história de Smalltalk e de permite que interfaces gráficas de usuário se adaptem automaticamente
temas atuais e aplicações comerciais da linguagem. às alterações sofridas nos dados de suas aplicações.
Nos capítulos 3 a 7 abordamos os aspectos básicos do ambiente No Capítulo 17 nós vamos desenvolver passo a passo uma aplica-
e da linguagem necessários a todo aquele que deseja programar em ção que utiliza todas as técnicas vistas nos capítulos anteriores. Esta apli-
Smalltalk. No capítulo 3 descrevemos o ambiente de programação do cação é um pequeno simulador de redes neurais, uma aplicação da
VisualWorks, versão padrão de Smalltalk e conceitos básicos de Smalltalk, Inteligência Artificial, que nos permitirá aplicar e explicar através de exem-
como a execução interativa de código e a inspeção de objetos. Nos outros plos em um contexto maior todos os conceitos vistos.
capítulos explanamos conceitos básicos de orientação a objetos, de como
a linguagem os implementa e como utilizá-los no desenvovlimento de apli- No Capítulo 18 tratamos do desenvolvimento de aplicações cli-
cações. ente-servidro para WWW. VisualWorks possui uma poderosa biblioteca de
classes denominada VisualWave que permite desenvolver de forma
No Capítulo 8 abordamos manipulação de arquivos externos e tranparente e interativa aplicações para Internet. Neste capítulo vamos
estruturas de acesso seqüencial, assunto importante para aquele que vai explicar esta técnica e exemplificá-la através de uma pequena aplicação
desenvolver aplicações utilizando arquivos em disco e desenvolver formas de comércio eletrônico.
específicas de comunicação de dados via rede de computadores.

20 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 21


Por Quê Smalltalk ?

Capítulo 2 +LVWyULFR

“The purpose of the Smalltalk project is to provide computer support


for the creative spirit in everyone”
[D aniel H . H . Inga lls - 1 98 1]

Neste capítulo você vai ter uma visão geral do histórico da Lingua-
gem de Programação Smalltalk. A história de Smalltalk está intimamente
ligada ao próprio desenvolvimento da idéia de orientação a objetos e esta
será também abordsada neste capítulo. Ao final do capítulo vamos ver
quais são as tendências atuais em orientação a objetos e qual o desenvol-
vimento futuro de linguagem.

Creio que um bom ponto de partida para se aprender uma lingua- As origens
gem de programação não seja o tão famoso programa "Olá Mundo!!!". Par-
ticularmente prefiro aprender sobre a origem da linguagem, quais são suas
idéias principais, e a que propósito ela se destina.
Pensando nisso, fiz uma pesquisa sobre a história do Smalltalk,
sua origem, precursores, idéias que inspiraram, pessoas envolvidas, etc.
No final dos anos 60, mais precisamente entre 66 e 68, uma nova
implementação da linguagem ALGOL tomou forma. Ela se chamava
SIMULA e foi idealizada e escrita na Noruega. Ela se destinava a criação
de aplicações modeladas através de várias partes distintas ou invés do,
isso possibilitaria que várias pessoas trabalhassem concomitantemente no

22 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Histórico

mesmo projeto. É claro que era possível em linguagens como ALGOL ou específicas e se destinavam quase que completamente a aplicações
Pascal trabalharem várias pessoas juntas, cada uma escrevendo uma numéricas. Então uma nova linguagem de programação se fazia neces-
parte do programa. O problema residia no momento de se agrupar as sária. Uma linguagem que fosse de fácil programação, que possuísse
várias partes do programa. A linguagem SIMULA se destinava a tornar uma sintaxe simples. Alan entrou para o PARC e o projeto da nova lin-
simples e rápido esta tarefa de agrupar as partes em um todo consis- guagem de programação ficou entre as prioridades do projeto Dynabook.
tente. Alan Kay foi buscar as idéias de que necessitava para a criação
O que existia no SIMULA era bem parecido com alguns concei- da nova linguagem em uma linguagem educativa escrita por Seymour
tos de orientação a objetos de hoje. Se definia uma classe em uma estru- Papert. Ela se denominava LOGO, possuía interface gráfica e se desti-
tura de classes organizada em uma hierarquia. Cada classe possuía nava ao ensino de programação para crianças. A linguagem LISP,
dados e comportamentos comuns a todas as instancias da classe. desenvolvida por MacCarthy na década de 50, forneceu o poder neces-
Porém naquela época SIMULA era considerada uma extensão de sua sário para a manipulação de símbolos (coisa até então inédita para as
linguagem pai, o ALGOL. As idéias de polimorfismo e herança não linguagens que só tratavam de números). Vários conceitos vindos do
faziam parte dos conceitos da linguagem. LISP formaram as bases da estrutura da linguagem Smalltalk. Até hoje
Mais tarde o conceito de TAD’s (Tipos Abstratos de Dados) foi todo método em Smalltalk retorna um valor, da mesma forma que uma
derivado dos conceitos preliminares da linguagem SIMULA e hoje, utili- função LISP. A facilidade com que se programa recursivamente em
zados em qualquer linguagem Estruturada. Smaltalk também é uma herança de LISP. Por fim, as idéias de modulari-
dade e os primitivos conceitos de orientação a objetos da linguagem
foram inspirados na linguagem de simulação de sistemas SIMULA.
O grupo de Nesta mesma época estava em andamento um projeto revolu-
pesquisas da cionário dentro do PARC (Palo Alto Research Center), um centro de pes- O útero para a gestação do Smalltalk estava criado. A equipe de
Xerox em quisas da XEROX na Califórnia. O projeto se intitulava Dynabook, e tinha Alam Kay trabalhou intensivamente, e no final de 1972 a primeira versão
Palo Alto como objetivo prover um ambiente completo tanto para crianças como do Smalltalk estava pronta. Foi a primeira linguagem realmente orientada
adultos, consistinod num novo computador revolucionário, de onde deri- a objetos porém ainda sem o conceito de herança. Uma linguagem de
varam posteriormente as idéias de Interface Gráfica, Sistema de Janelas, fácil programação destinada ao aprendizado de programação, com uma
Mouse ou apontador gráfico, Conexão entre computadores (usando linha sintaxe reduzida e clara. O nome surgiu do propósito a que se desti-
telefônica ou conexão para LAN’s usando Ethernet), reprodução de sons nava1. A idéia era que fosse tão fácil programar em Smalltalk quanto se
conectando-se a um aparelho de som e tantos outros. ter uma conversa informal. O programa era bem rudimentar, possuía
apenas alguns milhares de linhas. Ela foi traduzida para assembly e bati-
Em paralelo, um pesquisador da Universidade de Utah chamado
zada com o nome de Smalltalk-72.
Alan Kay trabalhava em um projeto chamado Flex, que era um sistema
de programação, com um novo desing para a simulação em computado- Em 1974, Smalltalk foi expandido para suportar capacidade grá-
res. Alan tomou ciência do projeto desenvolvido na PARC e propôs fica com o mapeamento de imagem por bits (os Bitmaps), e também o
varias extensões de software para o diretor geral do projeto Dynabook, conceito de memória virtual. Estes melhoramentos levaram ao primeiro
tais como as aplicações que conhecemos hoje como editores de textos sistema de gerenciamento de janelas2. Foi então chamado de Smalltalk-
simples, programas para desenho, para a criação de objetos 3-D, etc.
Porém na época as linguagens de programação existentes eram muito 1. Small talk em inglês significa “papo furado”.

24 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 25


Histórico

74. O conceito de herança só veio a ser implementado na versão do ano um esquema para a abertura da linguagem ao público em que continua-
de 1976. Tudo era baseado no conceito de classes, objetos, mensagens ria a publicar artigos pelo mundo, depois publicaria um livro e por fim dis-
e blocos. Na versão de 1976, também foi adicionado o conceito de byte- ponibilizaria o programa. Vários artigos foram publicados explicando os
codes e máquina virtual (VM - Virtual Machine), o que desvinculou a lin- conceitos por trás da linguagem e suas principais características. Alguns
guagem de programação do hardware específico de cada máquina e dos mais antigos e interessantes podem ser encontrados na revista Byte
também otimizou o que já existia. daquela época.

Bytecodes e Hoje o conceito de “linguagem interpretada baseada em código O livro planejado pela XEROX se multiplicou dando origem uma Adele
JAVA pré-compilado” representado pela geração de código intermediário série de três livros, com o título geral de Smalltalk - The Language and Its Goldberg e
usando byte-codes foi resgatado pela Sun Microsystems na linguagem Implementation. A organização e editoração da série ficou a cargo de seu livro
JAVA e é considerado a forma mais moderna e flexível de se produzir Adele Goldberg, uma das principais pesquisadoras do Projeto. Hoje os
programas ao mesmo tempo rápidos e independentes de máquina e de livros são conhecidos pela cor de suas capas, sendo chamados de Blue
sistema operacional. Isto permite que um programa em Smalltalk ou em Book, Orange Book e Green Book e formam a literatura mais clássica
JAVA desenvolvido em Microsoft Windows possa ser executado sem sobre Smalltalk, constituindo respectivamente: um manual de programa-
nenhuma modificação, nem mesmo recompilação, em uma Workstation ção, a referência da linguagem e a documentação da implementação da
Sun ou um Servidor IBM AIX ou em qualquer outra plataforma para a linguagem e da máquina virtual. Existia um plano em se lançar outro
qual exista uma versão da máquina virtual e vice-versa. Graças ao con- livro, porém ele nunca foi publicado. Ele se destinava a explicar uma fer-
ceito de byte-codes, a interpretação dos programas é feita de forma ramenta para aplicações interativas.
extremamente eficiente e rápida, sendo em alguns casos quase indife- A distribuição da linguagem, se deu através de fitas com uma
renciável de um programa compilado em “C”ou Delphi. versão portável da mesma. Esta versão portável consistia de um pro-
Em 1978, uma nova versão foi criada, porém apenas com o grama, a máquina virtual e um arquivo chamado imagem, onde todos os
código da anterior otimizado. Foi chamada, seguindo o padrão, Small- objetos do sistema residiam. A versão distribuída era chamada de
talk-78. Smalltalk-80 que nada mais era que uma versão mais enxuta do Small-
Neste momento, a pesquisa desenvolvida no Palo Alto Reseach talk-78. Neste ponto Smalltalk já possuía uma grande biblioteca de clas-
Center provocava curiosidade no mundo todo. Alguns artigos sobre o ses, e o mais interessante desta linguagem era que toda ela era
projeto do Dynabook e sobre sua nova e singularíssima linguagem de orientada a objetos. O compilador, a ambiente de programação e até
programação, o Smalltalk, eram publicados. O Dynabook nunca se tor- mesmo os números e caracteres eram objetos.
nou um produto comercial, em parte por seu custo altíssimo, porém o Smalltalk era então portável para qualquer plataforma que pos-
Smalltalk sobreviveu ao naufrágio do projeto. Neste ponto a XEROX suísse um sistema de bitmaps e outras poucas características e para o
acreditou estar na hora de tornar público o Smalltalk. A empresa montou qual existísse uma máquina virtual que interpretasse o byte-code gerado
pelo pré-compilador. A XEROX convidou então algumas empresas para
2. É interessante notar aqui, que o conceito de interação com o usuário de Smalltalk-74
desenvolverem as tais máquinas virtuais para suas plataformas. Dentre
de fato inspirou os sistemas de janelas atualmente em uso: MS Windows e X-Win- elas podemos citar a gigante Hewlett Packard, a emergente Apple Com-
dows. É muito citada na literatura uma visita de Bill Gates a Palo Alto, de onde voltou puter e a Digital Equipment. Depois desta primeira experiência que não
com “muitas idéias”.

26 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 27


Histórico

podemos deixar de citar acarretaram alguns problemas, uma grande Muitas outras implementações de Smalltalk foram criadas. Com Smalltalk
variedade de implementações do Smalltalk começou a surgir. Muitos pro- o surgimento do Linux uma versão baseada no ST-80, sob o Projeto para Linux
jetos se iniciaram dentro dos Estados Unidos, Japão e Europa. A Apple GNU, foi lançada com o nome de Smalltalk/X. Esta versão é de livre dis-
apresentou um particular interesse em relação a linguagem, e vários pes- tribuição e possui máquina virtual com código fonte aberto, conforme exi-
quisadores do projeto original foram para lá com o intuito de criar uma gem os termos de uso do GNU.
nova arquitetura de computador que deu origem ao sistema operacional Outro Smalltalk de livre distribuição que surgiu em 1996 foi o
da Apple baseado em interface gráfica. Squeak. Esta implementação é bem interessante pois foi desenvolvida
por um pequeno grupo de desenvolvedores, e entre eles constava nada
Smalltalk IBM A IBM não deixou por menos. Desenvolveu várias pesquisas e menos do que o pai do Smalltalk, Alan Kay. Ela possui características
criou a sua versão do Smalltalk chamada Smalltalk V. O Smalltalk V foi o bem interessantes com uma interface bem amigável e colorida. Atual-
primeiro Smalltalk a rodar também em DOS e tornou-se extremamente mente é utilizada pela Disney.
popular no final da década de 80. Posteriormente a IBM mudou o nome
de sua implementação de Smalltalk para VisualAge for Smalltalk, versão Atualmente a CINCOM inclui uma máquina virtual para Linux em
que possui diferenças mínimas em relação ao VisualWorks. sua distribuição não-comercial gratuita de VisualWorks, o que definitiva-
mente consolidou o VisualWorks como o Smalltalk padrão.
A XEROX não teve muito sucesso com suas implementações de
Smalltalk para suas Workstations. Em 1987 a XEROX criou uma nova As áreas de aplicação de Smalltalk são extremamente extensas: Aplicações
empresa chamada PARC PLACE para cuidar especificamente de negó- quanto mais complexo o problema a ser resolvido, maiores as vatagens comerciais e
cios relativos ao Smalltalk. Eles criaram várias versões baseadas no de se utilizar Smalltalk para o desenvolvimento de uma solução. projetos
Smalltalk-80 para diversas plataformas como IBM-PCs, Workstations da
Apollo e da Sun e para os Apple Macintosh. Em 1990 uma versão cha- No Brasil, Smalltalk ainda não é muito utilizado comercialmente,
mada ObjectWorks foi lançada. Ela era bastante comercial e possuía apesar de alguns bancos já possuírem partes de seus sistemas desen-
uma biblioteca de classes bem extensa. Depois da versão 4.1 o nome do volvidos em Smalltalk. Suas maiores aplicações residem nas áreas de
produto foi mudado para VisualWorks e ganhou um ambiente para pro- pesquisa e ensino, principalmente em Universidades Federais como a
gramação visual de interfaces gráficas de usuário. A Parc Place foi com- Universidade Federal de Santa Catarina - UFSC, Universidade Federal
prada pela CINCOM no final dos anos 90, que manteve a linha de do Rio Grande do Sul - URGS e Universidade Federal de Pernambuco -
produtos VisualWorks. O VisualWorks tem duas linhas. Uma de produtos UFPE.
comerciais com uma extensa biblioteca de classes e com inúmeras pos- Na Europa Smalltalk é extensivamente utilizado comercialmente,
sibilidades que vão desde a capacidade de se criar aplicações para rodar e praticamente todas as Universidades de Computação a utilizam como
na Internet, objetos para acesso de grandes bancos de dados como ferramenta para ensino do paradigma de programação orientada a obje-
ORACLE até objetos para o suporte de programação distribuída e ferra- tos.
mentas de controle de versões de código fonte. Ela também possui uma
Dois exemplos de aplicação comercial são a DEUTSCHE BANK,
distribuição não comercial para estudantes e curiosos, porém sem algu-
que em meados da década de 90 passou todo seu sistema de gerência
mas das funcionalidades da versão comercial, principalmente no que
de mercado financeiro para Smalltalk, e uma das maiores cadeias de
tange o controle de versões, e limitada apenas para uso individual.
supermercados da Europa, que na mesma época passou por uma rees-

28 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 29


Histórico

&RQFHLWRV%iVLFRV
truturação completa de seu setor de informática, passando todo o sis-
tema para Smalltalk. Capítulo 3
Essa Rede de Supermercados é um exemplo extremamente
interessante e ilustrativo da facilidade com que se pode aprender Small-
talk e portar um sistema desenvolvido em um paradigma completamente
GR$PELHQWH
diferente para o ambiente Smalltalk. Um dos autores deste livro trabalhou
no grupo de pesquisas da Universidade de Kaiserslautern responsável,
em 1995, por desenvolver e aplicar o programa de treinamento e recicla-
gem dos profissinais de informática desa rede de supermercados. Na
época, todo o sistema da empresa era desenvolvido em RPG, uma lin-
guagem de segunda geração, em plataforma AS 400. O perfil médio do
desenvolvedor de software empregado na empresa apresentava uma
média de idade de 40 anos e formação profissional de tecnólogo em pro-
cessamento de dados. A grande maioria não possuía quaisquer conheci-
mentos de orientação a objetos. Para o desenvolvimento do novo
sistema foram escolhidas estações Unix IBM AIX e VisualAge for Small-
Este capítulo tem por objetivo familiarizar o leitor com o ambiente
talk como ambiente de desenvolvimento. VisualAge foi escolhido em fun-
de desenvolvimento do VisualWorks. Neste capítulo passaremos ao leitor
ção de suas ferramentas de conectividade a mainframes, o que permitiu
uma vissão geral do ambiente de desenvolvimento/execução do Visu-
continuar utilizando os bancos de dados rodando em AS 400 a partir de
alWorks. Também apresentaremos os vários tipos de browsers, o works-
programas em Smalltalk. Dessa forma foi possível uma migração gradual
pace, o VisualLaucher e o UIPainter. O mecanismo de fileIn/fileOut e
dos sistemas em RPG para a nova base de software em Smalltalk. Em
parcels também terá vez neste capítulo, onde explicaremos para que serve
função do perfil dos profissionais que necessitavam ser reciclados, foi
e como funcionam todas essas partes do VisualWorks. Apresentaremos
desenvolvido um programa de treinamento especialmente voltado a pro-
por fim como podemos fazer para buscar ajuda dentro do ambiente de
gramadores experientes, mas sem nenhuma noção de orientação a obje-
desenvolvimento.
tos. Em função da antigüidade da plataforma RPG, isto foi um desafio
especial. A experiência foi um sucesso, todos puderam ser reciclados e
não foi necessário demitir funcioinários em função da mudança de tecno-
logia, o que demonstra claramente a facilidade de aprendizado do Small- 3.1 Smalltalk e VisualWorks
talk. Para programadores experimentados em outras linguagens de
Esse programa de treinamento foi adaptado e originou o Curso programação, principalmente aquelas de linha de comando, o VisualWorks
de Smalltalk regularmente ministrado como Curso de Extensão no pode parecer um tanto confuso. Para aqueles familiarizados com LISP ou
Departamento de Informática da Universidade Federal de Santa Catarina PROLOG o impacto será um pouco menor. A grande diferenciação do
e também propiciou muitas das experiências que nortearam o desenvol- Smalltalk para as outras linguagens de programação reside no fato de que
vimento deste livro. todo o ambiente de desenvolvimento está acoplado ao ambiente de execu-

30 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Conceitos Básicos do Ambiente Obtendo uma cópia do VisualWorks

ção. Podemos em suma dizer que não existe muita diferença em se edi- Dentre os pontos negativos podemos ressaltar uma menor per-
tar ou executar um programa em Smalltalk. formance de execução se comparada a linguagens como C ou Pascal, e
O VisualWorks é uma versão do Smalltalk que, como pudemos também a impossibilidade de se gerar código executável.
ver no histórico, é o sucessor principal do projeto da PARCPLACE. Nesta A seguir mostraremos ao leitor como se procede para se iniciar
seção introduziremos os principais conceitos que permeiam esta ferra- uma seção do VisualWorks e como devemos encerrá-la.
menta e a fazem única detre as linguagens de programação.
O VisualWorks é uma ferramenta de desenvolvimento interativo.
As classes são criadas e objeto podem ser intanciados e executados no 3.2 Obtendo uma cópia do VisualWorks
mesmo ambiente. O mais interessante desta interatividade proporcio-
O VisualWorks é uma ferramenta comercial de desenvolvimento
nada, como veremos mais adiante neste capítulo, é o fato de que qual-
tal como DELPHI ou Visual Basic. Como toda ferramenta comercial que
quer objeto pode ser inspecionado a qualquer momento e em qualquer
se prese, ela é paga. Mas o VisualWorks possui uma vrsão não cormer-
lugar do ambiente.
cial que pode ser utilizada por qualquer pessoa para uso pessoal ou edu-
Vale também ressaltar que o Smalltalk é uma linguagem inter- cacional. Esta versão não comercial possui algumas limitações em
pretata tal como JAVA, ou seja, código executável não é gerado, apenas relação a versão comercial, mas é perfeitamente usável .
bytecodes que são interpretados por uma máquina virtual. A grande dife-
Ela pode ser baixada diretamente do site da Cincom. O ende-
rença exsitente entre o bytecode gerado pelo VisualWorks e o gerado por
reço é o seguinte:
JAVA é que todos os objetos de todas as aplicações escritas em Small-
talk são colocadas dentro de um único arquivo que possui a extensão http://www.cincom.com
.im, a imagem. A abstração é que a imagem do VisualWorks é como um Vale dar uma olhadinha no site da fabricante. Periodicamente
“pequeno mundo“ onde tudo reside. Podemos então imaginar que se existem novas versões atualizadas para serem baixadas bem como notí-
essa filosofia aplica-se realmente a tudo, o compilador, o parcer e todos cias sobre o VisualWorks Smalltalk.
os objetos do ambiente de desenvolvimento também residem dentro da
imagem. A imagem é um arquivo relativamente grande, devido a esta
filosofia de agrupar tudo, então veremos que a imagem padrão tem seu 3.3 Arquivos com a Documentação do Smalltalk
tamanho girando em torno de 7 MB, e que após a eventual carga de
alguns parcels pode, tranquilamente, ter seu tamanho almentado para Na distribuição de instalação do VisualWorks existe um diretório
além de 10 MB. Parcels serão vistos mais a frente neste capítulo. chamado doc que contém vários arquivos pdf que compoem a docu-
mentação do VisualWroks. Neste diretório reside a documentação de
O fato do VisualWorks ser interpretado possui em si pontos bons
quase tudo o que existe no VisualWorks. O arquivo mais utilizado por
e maus. Uma de suas grandes vantágens é o fato de ser perfeitamente
programadores é sem sobra de dúvida o VisualWorks Application Deve-
portável para várias plataformas. Se o leitor der uma olhada no diretório
loper´s Guide, que contém uma descrição de boa parte do básico da lin-
bin da instalação do VisualWorks, poderá ver que lá se encontram mais
guagem. Vale ressaltar que este guia é um tanto superficial, deixando em
de 10 máquinas virtuais para diferentes plataformas. Dentre elas, Win-
aberto ou mal cobrindo alguns tópicos, tais como o uso de yourself
dows, Linux, Unix, Solaris, AIX, HP, etc. Outra grande vantágem de ser
ou thisContext que cobriremos nos próximos capítulos.
interpretado é a interatividade a qual já foi discutida acima.

32 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 33


Conceitos Básicos do Ambiente Arquivos com a Documentação do Smalltalk

Manuais A seguir, descreveremos cada um dos arquivos pdf contidos no dstcon.pdf -- VisualWorks Distributed Smalltalk Configuration
contidos no diretório doc. À medida que considerarmos necessário, vamos comentar Guide: Explica como configuar aplicações distribuídas em Smalltalk.
diretório doc seu conteúdo, sua utilidade e a ordem em que devem ser lidos. Na lista- dstpr.pdf -- VisualWorks Distributed Smalltalk Programmer´s
gem adiante vamos descrevê-los em ordemm alfabética. Reference -- Explica a idéia básica por detrás do desenvolvimento de
atug.pdf --VisualWorks Advanced Tools User´s Guide: Descreve aplicações distribuidas em Smalltalk.
algumas ferramentas do VisualWorks tais como o Parser, o Compilador, fixed_ars.pdf -- ARs Resolved in 5i.3 : lista os erros corrigidos
o gerador de relatórios, a ferramenta de benchMarks, etc..... na versão 5i.3.
bridge.pdf -- VisualWorks StORE BRIDGE: Descreve como se icslides.pdf -- VisualWorks Internet Connectivity Workshop.
migra uma aplicação usando o controle de versões do Envy para o con- Alguns slides do referido Workshop (sinseramente, eu nunca li isso!)
trole de versão usado pelo StORE. Tem muito pouca utilizade para usuá-
rios standalone, a não ser que estajam envolvidos em algum grande idlpr.pdf -- VisualWorks Distributed Smalltalk IDL Programmer´s
projeto de software. Reference: Referência da implementação de Smalltalk de IDL - Interface
Definiton Language, a linguagem padrão de intercâmbio de objetos utili-
comc_automation.pdf -- Using COM Conect Automation zada por Distributed Smalltalk e por CORBA.
Wizard: Descreve como se utiliza a ferramenta IAAutomationWizard para
publicação de automações COM. otcldg.pdf -- VisualWorks Opentalk Communication Layer
Developer´s Guide: provê informação sobre como implementar protoco-
comug.pdf -- VisualWorks COM Connect User´s Guide: Este los de comunicação e como desenvolver aplicações distribuidas utili-
guia descreve como usar o VisualWorks COM Connect para acessar ou zando Opentalk Communication Layer.
publicar objetos de dentro de Aplicações escritas em VisualWorks. Tam-
bém fornece referência para usar COMAutomation, ou seja OLE com visualworksfaq.pdf -- VisualWorks Frequently Asked Questi-
VisualWorks. ons: Como o próprio título já diz é um FAQ sobre Smalltalk. Muitas das
perguntas e respostas vêm do newssite comp.lang.smalltalk. Se
dbadg.pdf -- VisualWorks Database Connect Aplication Develo- o seu domínio de Internet, seja este um provedor comercial ou sua uni-
per´s Gride: Descreve o acesso a bancos de dados externos, ObjectLens versidade, colocar um serviço de news à sua disposição, sugerimos for-
e ODBC suporte para acessar bancos de dados relacionais dentro de temente que você assine este grupo de news, pois ele sempre tras
aplicações no VisualWorks. Descreve acesso genérico a banco de dados muitas informações e discussões úteis e atualizadas sobre Smalltalk. A
e também acesso específico para Oracle 7, Oracle 8, SYBASE CTLib e forma mais fácil de assessar um newssite é através da ferramenta Nets-
ODBC. cape Mail, onde você pode configurar acesso a vários servidores de
dllccug.pdf -- VisualWorks DLL & C Connect : Descreve o news simultaneamente.
mecanismo empregado para se utilizar bibliotecas escritas em C e DLLs vwadg.pdf -- VisualWorks Application Developer´s Guide: Prin-
em uma aplicação escrita em Smalltalk. cipal documento sobre o VisualWorks. Descreve a linguagem e o ambi-
dstadg.pdf -- VisualWorks Distributed Smalltalk Application ente.
Developer´s Guide: Apresenta o processo de desenvolvimento de aplica-
ções usando DST - objetos distribuídos em Smalltalk. Vale citar que DST
é compatível com CORBA.

34 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 35


Conceitos Básicos do Ambiente Instalando o VIsualWorks em sua máquina

vwiccb.pdf -- VIsualWorks Internet Connectivity Cookbook: Este wavescon.pdf -- VisualWave Server Configuration Guide:
arquivo é bem quente. Descreve como perfazer tarefas de internet tais Manual de configuração das classes servidoras HTTP que podem ser
como ftp, http, etc. usadas com aplicativos Smalltalk exportados para Internet.
vwintlg.pdf -- VisualWorks Internationalization Guide: O guia Existem ainda muito poucos livros que tratam de Smalltalk. A
de internacionalização indica técnicas e ferramentas em Smalltalk para maioria deles se reporta a versôes antigas e durante a elaboração deste
criar interfaces de usuário multiligües. Se você está desenvolvendo um livro realizamos uma pesquisa e não encontramos nenhum escrito em
software comercial para o Mercosul ou um software científico e deseja portugês ou traduzido. Ao consultar a bibliografia, o leitor verá que cita-
colocá-lo à disposição para ser baixado pela internet depois, é interes- mos alguns livos em inglês, mas a massa de documentos consultados
sante que ele seja multilíngüe. pelos autores deste livros foi artigos e páginas da web.
vwpluginadg.pdf -- VisualWorks PlugIn Application Developer´s Outro aviso importante ao leitor se refere às páginas que tratam
Guide: Da mesma forma que JAVA, Smalltalk também suporta a geração, do assunto na web. Existem muito boas referências porém a grande mai-
disponibilização e utilização de Applets na Internet. Para executar esses oria das páginas consultadas pelos autores demstrou conter um con-
applets a partir de um cliente remoto, é necessário que o browser possua teúdo superficial e até mesmo errôneo em alguns casos. Não queremos
um plugin especial (disponível somente para o Netscape) que é uma desta forma desencorajar o leitor a procurar mais informações pela Inter-
máquina virtual extremamente enxuta e especial para excução remota, net de maneira alguma, apenas alertamos para que tenha critério ao utili-
da mesma forma que você necessita do JDK para execução de código zar algum material publicado na mesma.
JAVA. Este manual ensina a desenvolver aplicações que usam esta
máquina virtual-plugin.
vwrn.pdf -- VisualWorks Release Notes: Descrição de caracte- 3.4 Instalando o VIsualWorks em sua máquina
rísticas novas da versão atual, que você acabou de baixar.
A partir da versão 5i.2 o VisualWorks vem com um estalador. Ele
walkthrough.pdf -- VisualWorks Walk Through: Um dos melho- ajuda tremendamente a intalar o software. Em versões anteriores o dire-
res tutoriais de Smalltalk. Comece por aqui. tório contendo todas as pastas referentes a instalação do VisualWorks
waveadg.pdf -- VisualWave Application Developer´s Guide: tinham que ser copiadas manualmente para o disco rígido.
VisualWave é a infraestrutura de VisualWorks para desenvolvimento de Não existe nenhuma grande diferença em instalar o VisualWorks
aplicações para Internet. Contém um conjunto de classes para transfor- em relação a qualquer outro software. Um ponto porém é interessante. O
mar suas interfaces de usuário em páginas HTML de forma transparente programa de instalação foi escrito em Smalltalk, e como toda a aplicação
e dois tipos de servidores HTTP que podem ser conectados com a sua em Smalltalk está contida dentro de uma imagem, uma imagem é execu-
aplicação Smalltalk. É de longe a forma mais fácil de desenvolver um tada para carregar o programa de instalação.
aplicativo para Internet: você desenvolve como se fosse um programa
O programa de instalação é executado diretamente quando o
normal, com janelas e interfaces gráficas e Wave exporta em tempo real
CD-ROM é inserido. Caso o sua máquina ou plataforma não suporte este
para um browser.
recurso, execute a imagem chamada install.im.
wavegs.pdf -- VisualWave Developer’s Getting Started with
Além de permitir a instalação, este programa também permite
VisualWave: Comece aprendendo a usar Wave por aqui.
que o VisualWorks seja removido de sua máquina.

36 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 37


Conceitos Básicos do Ambiente Iniciando e finalizando uma seção

3.5 Iniciando e finalizando uma seção


Como já vimos na seção anterior, devido ao fato de Smalltalk ser
interpretado, o procedimento básico para abertuda de uma seção é sub-
meter o arquivo contendo o bytecode (a imagem) à máquina virtual.
Geralmente, trabalhando sobre a plataforma windows ou Linux,
costuma-se associar os arquivos com extenção .im à máquina virtual da
plataforma em quetão. Isso permite alguma flexibilidade, sendo necessá-
rio apenas clicar sobre um arquivo .im para iniciar uma seção. A Outra
alternativa é passar a imagem como parámetro ao se executar a
máquina virtual ou simplesmente arrastar uma imagem para cima da
máquina virtual.
Acreditamos que o leitor já esteja familiarizado com o sistema
operacional que costuma utilizar e sabe como proceder para fazer a
associação, apenas a título de exemplo apresetaremos como se deve
proceder para associar os arquivos .im a máquina virtual do Smalltalk a
partir da plataforma windows.
Clique sobre um arquivo .im . Como nenhum aplicativo está
associado a janela para associação de arquivos mostrada na figura 3.2
na página 40 será aberta.
A máquina virtual do VisualWorks não aparecerá na lista dos
Figura 3.1 Janela de Instalação do VisualWorks 5i.3
softwares registrados. Clique então em <Other...> para indicar a localiza-
ção da máquina virtual. Vá até o diretório bin da instalação de seu Visu-
Existe um arquivo pdf chamado Install.pdf no diretório
alWorks e selecione o arquivo visual.exe. Selecione etão o check box
padrão da instalação do VisualWorks que descreve algumas peculiarida-
“Always use this programa to open these files“ na janela de associação e
des da instalação do VisualWorks. Caso você tenha algum problema na
clique em ok.
instalação, (coisa muito rara diga-se de passagem) reporte-se a este
documento. Desta forma, para iniciar uma seção do VIsualWorks bastará cli-
car sobre a sua imagem.
Comumente, cada usuário possui a sua própria imagem de tra-
balho. A primeira vez em que se entra no VisualWorks o costume dita
que se abra a imagem padrão “visualnc.im“ que se encontra no dire-
tório image da intalação do VisualWorks. Logo em seguida a abertura da
seção, deve-se salvar a imagem com um nome que melhor lhe aprouver.

38 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 39


Conceitos Básicos do Ambiente Iniciando e finalizando uma seção

Figura 3.3 Janela de localização de arquivos do windows


Figura 3.2 Janela de associação de arquivos do windows
arquivos que foram deixados abertos, pois tratam-se de recursos que
Isso fará com que uma nova imagem seja criada. A partir deste serão desalocados pelo sistema operacional.
momento, você possui uma imagem de trabalho. Vale citar que não é
aconselhável usar a imagem padrão como imagem de trabalho, pois se Existem várias maneiras de se salvar uma imagem. A mais
outro usuário ou até mesmo você desejar criar uma outra imagem de tra- comum é clicando no botão de menu que possui um disquetinho. Uma
balho, a matriz original livre de alterações do usuário não existirá mais. caixa de diálogo será aberta para que você digite o nome da imagem.
Esta janela também aceita que se indique o caminho onde se deve salvar
Após editar uma imagem, criando classes, instancias, reposicio- a imagem.
nando janelas, adiconando código ao workspace, etc, você deve salvar a
sua imagem. Ao fazer isso todas as suas alterações, sejam elas de ambi- Caso nenhum caminho seja indicado, a imagem será salvada no
ente tais como quais janelas estão abertas em que posição, ou o código diretório padrão, que no caso é onde se encontra a imagem no momento
contido no workspace ou até mesmo quais figuras estão carregas dentro em que ela foi aberta.
da imagem serão salvas. Quando a sua imagem for aberta novamente, Outra maneira de se salvar a imagem é quando se seleciona a
tudo voltará ao estado em que estava exatamente antes da imagem ser opção para fechar a imagem, seja através do ítem de menu ou clicando-
salva. Porém existem algumas coisas que não persistem, tais como se no x para fechar a janela.

40 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 41


Conceitos Básicos do Ambiente Os principais arquivos do sistema

A terceira opção salva o trabalho feito na seção corrente e


depois fecha a imagem.Por último, a quarta opção cancela e volta para o
ambiente de desenvolvimento.

3.6 Os principais arquivos do sistema


Basicamente, um sistema Smalltalk é composto por 4 arquivos.
• a imagem (arquivo.im)
Figura 3.4 Janela de salvamento da imagem
• o arquivo de sources (.sou)
A janela apresentada na figura 3.5 será então aberta, solici- • o arquivo de alterações (arquivo.cha)
tando que uma das quatro opções seja selecionada. A primeira requisita • a máquina virtual (arquvo.exe no caso do Windows)
que o laucher seja fechado, neste caso após todas as outras janelas Na imagem estão encerrados todas as classes definidas, todos
serem explicitamente fechadas, um novo laucher será aberto permitindo os objetos instanciados, o compilador, o ambiente de desenvolvimento,
assim que novas janelas sejam abertas ou que se feche efetivamente a enfim, tudo, em forma de bytecodes. A imagem é um arquivo genérico,
imagem. sendo perfeitamente utilizável em qualquer plataforma.
A máquina virtual é um programa que tem como função traduzir
o bytecode (código intermediário) gerado pelo compilador para diretivas
da máquina hospedeira. A máquina virtual deve ser escrita especifica-
mente para a plataforma em que será executada.
O arquivo .sou contém o código fonte da biblioteca padrão do
sistema. É este arquivo que é acessado quando selecionamos em um
browser para ver o código de um determinado método do sistema. Um
dos erros mais comuns é quando o path deste arquivo está errado. Isso
faz com que o VisualWorks não o encontre e toda vez que a visualização
do código de um método da biblioteca de classes for selecionado, ape-
nas o seu código decompilado será mostrado. Para concertar esse even-
Figura 3.5 Janela de saída do VisualWorks tual erro, ajuste o path deste arquivo na janela Setings que será vista
mais a frente.
A segunda opção fecha a imagem sem que as alterações feitas
na última seção sejam salvas. Se por acidente esta opção for selecio- Este mecanismo fornece um alto grau de modularidade e porta-
nada ainda existe uma maneira de recuperar o trabalho feito. Ela será bilidade.
vista mais a frente quando apresentarmos o mecanismo de gerencia-
mento do arquivo de mudanças (.cha).

42 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 43


Conceitos Básicos do Ambiente Browsers

Além disso, a partir do laucher podemos abrir todas as outras


3.7 Visual Laucher ferramentas do VisualWorks, tais como o Workspace, os browsers, o pro-
A primeira das janelas que compoem a interface que apresenta- grama para procura e execução de recursos, a aplicação WYSIWYG
remos será o Laucher. Ele reune uma série de menus e um menuButton para criação de interfaces gráficas (UIPainter), O gerenciamento de
onde as ferramentas do ambiente podem ser acionadas. A parte inferior banco de dados, a janela de configurações do sistema além de ser a par-
do Laucher é conhecida como Transcript. Ele é uma saída textual padrão tir dele que podemos gerenciar o nosso arquivo de alterações .cha.
do Smalltalk. É extensivamente utilizado durante testes onde é mandado Todas essas funcionalidades serão cobertas mais a diante neste capí-
que se escreva os resultados. Podemos referenciar o Transcript exata- tulo.
mente como escrevemos.

3.8 Browsers
Os browsers são as ferramentas básicas para edição de progra-
mas. E através deles que criamos novas classes e é por onde podemos
analisar o código da biblioteca de classes. Existem três tipos de brow-
sers. Eles podem ser acessados a partir do Laucher, nos 3 botões mos-
trados na figura 3.7 .

Figura 3.6 Laucher do VisualWorks Figura 3.7 Botões para abertura dos browsers

Como descrito na seção anterior, se o laucher for eventualmente Da esquerda para a direita temos o browser organizado por
fechado, para que a imagem possa ser salva ou para que se feche a NameSpaces (NameSpaces serão vistos em detalhes mais a frente no
seção será necessário que o laucher seja novamente aberto. Isso pode livro), o Browser organizado por Categorias e o browser organizado por
ser feito de duas maneiras. Fechando todas as demais janelas fazendo parcels. Como podemos ver, cada um destes browsers se destina a uma
assim com que o laucher seja reaberto ou executando o seguinte aplicação específica dentro do ambiente de desenvolvimento. Para a cri-
comando mostrado no exemplo 3.1 . Para saber como executar este ação de classes e métodos o mais indicado é o organizado por catego-
comando, veja mais adiante neste capítulo a seção “Executando rias (botão do meio). Os outros browsers serão abordados em maiores
Código”. detalhes no decorrer do livro. Tomemos o browser acionado pelo botão
do meio como objeto de estudo então.
VisualLauncher open. Ele permite que o programador inspecione todas as classes e
Exemplo 3.1 Reabertura do visual laucher seu respectivo código fonte que estão contidos dentro da imagem. Como
podemos ver na fig. , o system browser é dividido em 5 quadros e um

44 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 45


Conceitos Básicos do Ambiente Browsers

destina a visualização e edição de métodos. Ainda existem 3 radio but-


Lista de Lista das Classes Lista dos Protocolos Lista dos Métodos tons que servem para alterar entre a visão dos métodos de classe e
Categorias pertencentes à de Métodos pertencentes pertencentes ao métodos de instância e variáveis estáticas. A diferença entre os dois
de Classes Categoria selecionada à Classe selecionada Protocolo selecionado tipos de métodos e variáveis estáticas serão vistos mais a frente. O efeito
de selecionar um dentre os três botões é que os dois últimos quadros
mostrarão informações distintas.
Existe uma série de funções úteis que podem ser acionadas a
pardir do System Browser. Dentre elas podemos citar o mecanismo de
fileIn/fileOut, ferramenta de busca de classes e métodos, podemos impri-
mir código, também podemos ver todas as classes que implementam um
determinado método, existe uma ferramenta que explica um determinado
código selecionado, etc.
Nesta seção apresentaremos algumas delas, deixando para o
leitor descobir a funcionalidade das restantes. Não se assuste. O system
browser pode parecer um tanto assustador a primeira vista, mas a
medida que você se acostuma com ele, chega a conclusão de que é uma
ferramenta extremamente intuitiva e fácil de se usar.

O System Browser fornece uma ferramenta para pesquisa de Procurando


classes. Ela não é nada mais que uma simples caixa de diálogo onde por uma
você pode digirar uma expressão regular (tal como no Linux utilizando * e classe ?
Código do Método ? para qualquer caractere, etc). É interessante ressaltar que embora o
selecionado Smalltalk faça diferenciação entre maiúsculas e minúsculas, a ferra-
menta de busca não faz, então não se preocupe com a maneira em que
o nome da classe foi digitado.
Figura 3.8 O System Browser do VisualWorks Para acionar o mecanismo de busca de classes clique com o
botão direito do mouse sobre o primeiro dos views (o category view). O
menu. O quadro mais abaixo é o codeView. É nele que os métodos menu popup mostrado na figura 3.9 na página 48 será aberto. Selecione
podem ser editados e visualizados. Os quatro quadros mais a cima, são a última opção <Find Class...> A janela mostrada ao lado será então
respectivamente, o CategoryView, o ClassView, o ProtocolView e o aberta. Nela você deve digitar a expressão a ser verificada.
MetodView. O primeiro e o terceiro são puramente organizacionais, só
servem para colocar uma certa ordem em suas classes, tanto na sua Caso a pesquisa retorne mais de uma ocorrencia, uma segunda
organização global como na interna. O segundo Quadro lista classes e é janela será aberta listando todas as ocorrencias que batem com a
o ponto de partida para a criação de novas classes. O último quadro se expressao definida. A partir dai, basta clicar sobre a classe que se deseja

46 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 47


Conceitos Básicos do Ambiente Browsers

Como vimos anteriormente, o System browser organiza as clas- Adicionando


ses em categorias e os métodos em protocolos. Esta estratégia embora uma nova
puramente organizacional, proporciona uma maior facilidade de manipu- categoria
lar o código escrito, pois como veremos mais a frente no livro, a idéia do
Smalltalk é possuir apenas métodos curtos, isso acarretanto em uma
grande quantidade dos mesmos.
Para criar uma nova categoria para classes clique com o botão
direito do mouse sobre o view de categorias. Selecione o ítem <Add...> .
A janela mostrada na figura 3.11 na página 49 será então aberta
Figura 3.9 Menu PopUp do View de Categoria e janela para localização de classes
requsitando uma string para o nome da categoria e também listando na
parte inferior do janela uma lista de todos os NameSpaces contidos na
verificar e o browser será automaticamente redirecionado para a defini- imagem. Você deverá obrigatoriamente escolher um dentre os listados.
ção da classe. Veremos NameSpaces mais a frente, por hora selecione o ítem Smalltalk
e clique em OK.

Figura 3.10 Jjanela de multiplas ocorrências de uma pesquisa

Figura 3.11 Janela para criação de categorias

48 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 49


Conceitos Básicos do Ambiente Browsers

A nova categoria será então adicionada a lista de categorias do


Categoria na qual a Template para a criação da classe.
System Browser. Note que esta lista está sempre em ordem alfabética.
nova classe vai ser Aqui você pode editar o nome e as
incluída variáveis de instância e classe e
Adicionando O mecanismo para a adição de protocolos é similar ao estudado indicar qual será sua superclasse.
um novo no tópico acima, porém nenhum NameSpace é solicitado para que se
protocolo de realiza esta operação. Apenas o nome do novo protocolo é requerido.
métodos Para adicionar um novo protocolo, clique com o botão direito do mouse
sobre o view de protocolos e selecione a opção Add.... .
A janela apresentada na figura 3.12 na página 50 será então
aberta. A mensagem “Enter new category name“ é um tanto quanto con-
fusa. Parece que estamos adicionando uma categoria e não um proto-
colo. Abstraia, digite o nome do protocolo que se deseja criar e clique em
OK. O novo protocolo será automaticamente adicionado ao view de pro-
tocolos.

Figura 3.12 Janela para criação de protocolos


Figura 3.13 Template para a criação de classes. A nova classe criada será neste caso
Template Uma vez que a categoria de classe da sua aplicação está criada, incluída na categoria “Colections-Arrayed” selecionada.
para a podemos então adicionar uma nova classe. Para a criação de classe. o
criação de VisualWorks através do System Browser fornece um template. Este será mente sobre o referido ítem de menu. Na parte inferior do Browser (edit
classes então traduzido em uma classe propriamente dita. Não dê muita importâ- view) um template será mostrado. A priori, apenas o nome da classe e o
nia para essas peculiaridades e passe a criação de classes. nome de sua classe pai devem ser preenchidos. Os outros campos do
template serão discutidos mais a frente no livro.
Para criar uma nova classe, clique com o botão direito do mouse
sobre o class view e selecione a opção <Add Class...> . Como podemos Feito isso clique com o botão direito do mouse sobre o view que
ver, este ítem de menu possui ainda 3 sub ítens. Deixemos esse detalhe contém o template (edit view) e selecione a opção <accept>. Esse ítem
por hora de lado, ele será melhor explicado mais a frente. Clique nova- de menu chama o parser e depois o compiler e o código da nova classe

50 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 51


Conceitos Básicos do Ambiente Workspace

será automaticamente criado. esta é realmente uma das grandes vantá- Geralmente é muito útil ter-se uma noção da topologia da árvore Expandindo a
gens de Smalltalk. não necessitarmos explicitamente compilar o código. de hierarquia de uma determinada classe. Isso nos facilita concluir onde hierarquia de
O processo de compilação anda em paralelo com o de criação de clas- um método que foi enviado a instancia de uma classe foi realmente classes
ses e métodos. implementado, além de mostrar claramente a estrutura que compõe uma
Feito isso, a sua nova classe será então adicionada à lista de classe.
classes daquela categoria finalizando assim o processo para a criação Isso pode não parecer muito útil a primeira vista, mas durante o
de uma nova classe. tempo em que o leitor for se familiarizando com o Ambiente, inerente-
mente, a necessidade de uma ferramenta como essas lhe saltará aos
Template Similarmente ao template para a criação de classes, o template olhos.
para a para a ciração de métodos define em geral onde se deve colocar o nome Quando uma classe é selecionada para que tenha a sua hierar-
criação de do método, o comentário, a lista de variáveis temporárias e o código pró- quia expandida, o que acontece de fato é a abertura de um novo brow-
métodos priamente dito. Em geral, quando o template de métodos é aberto, sim- ser, um tipo especial chamado hierarquical Browser. Sua principal
plesmente delete o texto e entre com a descrição do método. característica é apresentar a hierarquia de classes de uma dada classe.
Para se criar um novo método, basta que se selecione um dos Note que este browser só tem 3 listas, que são: classes (organizandas
protocolos de métodos de uma classe. O template será mostrado imedia- hierarquicamente), protocolos e métodos. O nível de categorias é abstra-
tamente no campo inferior do browser. Delete-o, digite seu método e ído neste caso.
então clique com o botão direito do mouse sobre o método. Selecione a Para abrir um Hierarquical browser clique sobre uma classe na
opção <accept>. Isso fará com que o VisualWorks chame o compilador lista de classes no System Browser e selecione a opção <Spawn Hierar-
que verificará a corretude de seu código e então, caso esteja tudo certo, chy>.
compila gerando o bytecode correspondente e o adiciona a imagem.

Listando os Embora utilizemos protocolos para a organização de nossos


3.9 Workspace
métodos métodos, em certas situações pode ser bem complicado encontrar um
dado método. Ele pode por exemplo ter sido implementado em uma O Workspace, como o próprio nome já indica é um espaço de
superclasse a que esta o usando. Percorrer protocolo por protocolo seria trabalho onde código Smalltalk pode ser composto e testado sem fazer
uma tarefa um tanto quanto custosa. parte de uma classe concreta. Você pode considerar o Workspace como
Para facilitar esta procura de um método que não sabemos onde um editor de texto, onde você pode executar qualquer código que você
foi implementado, o VisualWorks possui uma ferramenta que lista todos escreveu, simplesmente selecionando-o e usando o ponto de menu <do
os métodos da classes selecionada. Sobre o view de protocolos no brow- it>1. Ele é de extrema utilidade durante o processo de desenvolvimento e
ser, clique com o botão direito do mouse. Selecione então o ítem <Find depuração de classes pois permite um teste rápido. Workspaces e o
Method ...>. Uma lista contendo todos os métodos daquela classe será
então aberta. Clicando em qualquer um deles, uma nova janela será 1. Na verdade, qualquer lugar onde texto pode ser executado em Smalltalk é um ambi-
ente onde você pode invocar o ponto de menu <do it> e executar qualquer parte do
aberta com a implementação do método. código que aí está. Por uma questão de organização referimo-nos ao Workspace
como o lugar onde iste deve er feito.

52 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 53


Conceitos Básicos do Ambiente Executando código

Hierarquia de Classes Lista dos Protocolos Lista dos Métodos


à qual a Classe escolhida de Métodos pertencentes pertencentes ao
pertence à Classe selecionada Protocolo selecionado

Figura 3.15 Workspace do VisualWorks

3.10 Executando código


Como já dissemos anteriormente, podemos executar parcelas
de código em qualquer lugar dentro do ambiente de desenvolvimento do
VisualWorks. Para isso bastando que possamos editar textos no local
escolhido. Embora possamos escrever tanto em browsers como no
transcript, existe um lugar pré-definido para nossos testes, este lugar é o
workspace visto na seção anterior.
Figura 3.14 Exemplo do Hierarchy Browser para uma classe denominada “Retangulo”.
O processo de se avaliar parcelas de código é extremamente
Transcript (visto junto com o Laucher) são geralmente utilizados em simples, porém como o mecanismo empregado é completamente dife-
paralelo, onde os testes de programação são editados e avaliados no rente do encontrado em qualquer outra liguagem de programação
Workspace e as saídas são direcionadas para o Transcript. (embora seja realmente trivial), vamos explicar nesta seção passo-a-
passo como devemos proceder. A medida que o leitor for se familiari-
O workspace apresentado na fig.2.16 é o mais simples, e já vem zando com o Smalltalk perceberá que este processo será intuitivo,
como parte integrante da imagem básica do VisualWorks. Existem outros embora a primeira vista, para programadores esperimentados em lingua-
Workspaces com várias outras capacidades, tais como o WorkspaceOr- gens de programação como C++ e Pascal possa parecer completamente
ganizer, que podem ser acrescentados a sua imagem. Ele é distribuído estranho.
como um parcel e será visto mais a frente neste capítulo.
Em primeiro lugar devemos selecionar a parcela de código que
desejamos executar. Isso pode ser feito como procedemos em qualquer

54 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 55


Conceitos Básicos do Ambiente Executando código

outro editor de textos, usando o mouse ou através das teclas de desloca- janela de inspeção contendo o estado interno do ultimo objeto retornado
mento e do shift. pela parcela de código (este processo será explicado em detalhes mais a
frente no livro). Por último, a quarta opção permite que debuguemos a
parcela de código através da ferramenta de debug do Smalltalk.

Figura 3.16 Código selecionado no workspace Figura 3.17 Popup menu aberto a partir do botão direito do mouse

Uma vez que a parcela de código alvo esteja selecionada, deve- Na figura 3.18 na página 58 podemos ver o resultado de esco-
mos clicar com o botão direito do mouse sobre o cõdigo. Isso fara com lhermos a segunda opção (print it). O conteúdo da coleção criada é então
que um menu popup seja aberto. A partir deste menu, temos quatro impresso no workspace. Note que o texto é simplesmente escrito no
opções que nos permitem executar o código. Estas quatro opções são workspace e não faz parte do código. por isso ele já é impresso selecio-
encotradas na quarta seção de cima para baixo na figura 3.18 . Todas as nado pois deve ser deletado, a menos que você queira comentá-lo.
quatro opções, do it, print it, inspect it e debug it executam a parcela de
Caso o código lhe pareça difícil de entender, não se preocupe, à
código selecionado. A diferença é que a primeira opção simplesmente
medida que avançar pelos capítulos, você vai compreender todos os
executa o mesmo, a segunda executa e chama o método2 e redireciona
aspectos da sintaxe do Smalltalk. Por enquanto concentre-se neste
a saida para onde o código se encontra. A terceira opção abre uma
aspecto importante e novo, que é a capacidade de, em Smalltalk, você
selecionar qualquer trecho de código, em qualquer lugar, e simplesmente
2. O método printOn: é definido na classe Object e é responsável pela forma com que mandar executá-lo.
um objeto será impresso. Ele é usado em diverças partes do Ambiente de desenvolvi-
mento e será melhor esplicado no capítulo 9.

56 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 57


Conceitos Básicos do Ambiente UIPainter

Lista de todas subclasses de Lista de todos recursos (menus,


ApplicationModel que definem janelas e ícones) definidos pela
algum novo recurso de interface classe selecionada

Figura 3.18 Resultado do execução da opção print it Figura 3.19 Janela do Resource Finder

3.11 Resource Finder 3.12 UIPainter


O resource finder é uma ferramenta poderosa do VisualWorks. O UIPainter é a ferramente WYSIWYG5 do Visualworks para
Ele mantém uma lista de todos os “recursos editáveis”3 presentes na edição e manutenção de interfaces gráficas. Seu funcionamento é bem
imagem e permite a rápida edição dos mesmos. similar aos editores do VisualBasic ou do Delphi porém um pouco menos
rico em termos de detalhes.
Na figura 3.19 vemos a classe LabCompGraf selecionada na
caixa de listagem da esquerda e o item “windowSpec“4 selecionado na A Cincom está investindo grande esforço em tornar esta ferra-
caixa da direita. Os botões da parta superior do resource finder permitem menta mais completa. Durante a impressão deste livro, uma nova versão
que editemos o recurso, lancemo-no caso seja um programa e opera- do VisualWorks foi liberada (vw5i.4), ela já contém varias melhorias em
ções básicas como remoção e remomeação. relação a verção 5.3 abordada neste livro. Vale a pena dar uma olhada

3. Recursos editáveis são: imagens, menus, interfaces gráficas, etc. 5. Termo comumente utilizado em Informática para denomenar editores que permitem
4. windowSpec é o nome padrão dado a especificação de uma janela. Este tópico será definirmos interfaces e documentos da mesma maneira em que os vemos (O que você
visto em detalhes mais adiante. vê é o que você obtém)

58 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 59


Conceitos Básicos do Ambiente UIPainter

acaba de ser feita seja salva como um recurso em uma classe especifi-
cada.
O UIPainter também possui a operação define que só é abilitada
uma vez que a interface já está instalada. Ela permite que operações
básicas dos componentes que geralmente deveriam ser explicitamente
definidas pelo programador sejam criadas de forma automatizada.

Esta janela contém todos os componentes que uma janela pode Palette
conter. Seu funcionamento é bem parecido com o encontrado no VB e
DELPHI, escolhe-se o componente a ser inserido na janela e arasta-o
Interface do aplicativo Paleta até a posição desejada. Na parte inferior da janela é apresentado o nome
Paleta que você está desen- para do componente selecionado.
para volvendo. Inicialmente formatação
adição Uma boa característica encontrada na palette são os dois botões
ela se chama sempre de
de Unlabeled Canvas interfaces encotrados no canto superior direito e esquerdo, eles permitem que sele-
componentes e menus cionemos um objeto para adição simples ou multipla ao canvas.

O canvas é a janela propriamente dita. Ela recebe este nome Canvas


devido a fatos históricos referindo-se a analogia existente entre a criação
de uma interface gráfica através do UIPainter e de se desenhar sobre
Figura 3.20 UIPainter com suas 3 janelas mais comuns abertas uma tela (canvas).

Ele é dividido em 3 janelas principais que permitem a edição da Seu funcionamento é bem simples, ele é a superfície gráfica
interface, seleção de componentes e operações básicas sobre o projeto onde podemos desenhar interfaces e possui propriedades como qual-
da interface. A seguir descreveremos cada uma delas e apresentaremos quer janela em outras linguagens de programação.
ainda outras duas ferramentas, o menu editor e o image editor.
Se o leitor já possui alguma esperiência em desenvolvimento de Properties
interfaces em Delphi ou VB deve estar se perguntando: Mas e as proprie-
Canvas Tool Esta janela permite operações básicas sobre a edição da inter-
face tais como alinhamento e redimencionamento de componentes. Tam- dades dos componentes ?
bém possui botões e entradas de menu para perfazer duas operações É importante observar que a maioria das ações em smalltalk são
muito importantes durante o desenvolvimento de interfaces gráficas no suportadas em menus. Eles são utilizados exaustivamente em todo o
VisualWorks, “DEFINE“ e “INSTALL“. ambiente de desenvolvimento e a medida que o leitor for se acostu-
Uma vez que a interface está completamente desenhada e mando com o smalltalk verá que é extremamente prático tem todos os
todas as propriedades dos objetos estão definidas a operação de install comando “ao alcance do botão direito do mouse”.
deve ser executada. Ela faz com que a especificação de interface que

60 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 61


Conceitos Básicos do Ambiente UIPainter

Então é de se esperar que as propriedades possam ser acessa- A grande maioria destas variáveis de ambiente podem ter seus
das através de um menu acionado pelo botão direito do mouse. A figura valores alterados através da janela Settings. Esta janela pode ser aberta
3.21 na página 62 mostra a janela de propriedades de um botão através do menu <File> opção <Settings>, conforme mostrado na figura
3.22 na página 63.

Figura 3.21 Janela de propriedades de um botão

Settings & Como já foi dito, o ambiente de desenvolvimento do VisualWorks


VisualWorks está completamente integrado com o ambiente de execução dos progra-
Settings mas. As vantágens e desvantágens desta característica já foram discuti-
Home das, o que se faz necessário salientar é a existência de variáveis de Figura 3.22 Janela de configuração do VisualWorks
ambiente que definem muitas coisas com relação ao ambiente.
Vale a pena dar uma boa olhada em todas as opções contidas
Por exemplo podemos selecionar qual a linguagem utilizada nesta janela. Se alguma coisa no ambiente começar a dar problemas
para escrever os arquivos gerados pelo comando de fileOut, ou qual o depois de alguma alteração feche a imagem sem salvá-la e ela não
tamanho máximo de que o canvas pode atingir (em pixels), a aparência sofrerá nenhum prejizo.
das janelas e a localização dos parcels que o ambiente pode utilizar.
Porém uma variável de ambiente é especialmente importante.
Trata-se daquela que representa o caminho onde o Smalltalk está insta-

62 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 63


Conceitos Básicos do Ambiente Carregando e Salvando Código Fonte

lado. Muitas outras variáveis de ambiente fazer referência a esta variável linguagens de programação, demorar-nos-emos a explicar em que con-
e se está esntiver apontado para o caminho errado muitos problemas sistem.
ocorrerão com a sua imagem. De fato este é o problema mais comum
que um iniciante em Smalltalk irá encontrar. Problemas como código Como o leitor já sabe, todo o código produzido fica inserido den- Mecanismo
decompilado, e parcels que não podem ser encontrados são em geral tro do arquivo imagem. Desta forma não existe aquele conceito tão de fileIn/
causados pela incorreção do caminho desta variável de ambiente. comum em outras linguagens de programação de se salvar o seu arquivo fileOut
Ela pode ser alterada através de uma janela especial unica- de código fonte separado do executável. No Smalltalk eles são uma
mente com esta finalidade que pode ser aberta através do itém de menu coisa só.
<File> opção <Set VisualWors Home>. Porém, não são raros os casos onde se deseja possuir uma
cópia textual do programa editado, e também situações onde desejamos
fazer backups apenas de certas alterações ou situações onde desejamos
3.13 Coletando o Lixo compartilhar um pedaço de código com um colega por motivos vários.
Desta forma, o mecanismo de FileOut permite que se salve uma Catego-
Uma das grandes facilidades do Smalltalk reside no fato de que ria, Classe Propocolo ou somente um método em um arquivo separado.
na maioria dos casos o programador não precisa se preocupar com a Também é permitida a seleção de métodos esparços por várias classes e
liberação de memória, está tarefa enfadonha é feita automaticamente por qualquer outra combinação que o leitor imaginar ou sentir necessidade.
uma parte do ambiente conhecida como Garbage Collector (ou coletor
de lixo). O processo de FileIn, como já era de se esperar, é exatamente o
oposto. Tendo como base arquivo previamente gerado pelo Smalltalk,
O fato é que as vezes o coletor de lixo pode demorar um pouco permite que o código nele contido seja incorporado a imagem.
para perceber que certos objetos já podem ser liberados. Desta forma
existe um ítem no menu <File> opeção <Collect all Garbage> que per- Duplicatas de qualquer tipo serão sobrepostas com os dados
mite acionar o coletor de lixo explicitamente. Em geral porém não existe contidos no arquivo.
muita necessidade de se preocupar com isso.
Atualmente o Smalltalk permite que que estes arquivos sejam Salvando em
Existem outras situações como veremos mais a frente em que o XML ou em
escritos em duas linguagens, Smalltalk Chunk Source Code, que nada
programador deve se preocupar com a liberação de memória, devido a texto chunk
mais é do que texto Smalltalk passível de ser interpretado pelo compila-
fenomenos conhecidos como referência circular e outros, mais isso será
dor Smalltalk e também editado em qualquer editor de programas, e XML
abordado mais a frente no livro.
Source Code. Se uma determinada parcela de código for salva utilizando
XML e tentar ser carregada prevendo Smalltalk chunk ou vice-versa um
erro será gerado.
3.14 Carregando e Salvando Código Fonte
A linguagem utilizando para abertura e escrita de arquivos
O processo de FileIn e FileOut já foi citado lagumas vezes (FileIn e FileOut) pode ser definida através de uma variável de ambiente
até aqui no livro, e por ser até certo ponto uma operação pouco usual encontrada na janela Settings.
senão quase desconhecida para programadores que conheçam outras

64 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 65


Conceitos Básicos do Ambiente Geração de Pacotes de Programa: Parcels

Uma boa explicação do funcionamento do browser de parcels


3.15 Geração de Pacotes de Programa: Parcels além de muitos detalhes podem ser encontrados na referência bibliográ-
O VisualWorks implementa, além do mecanismo de FileIn e fica ao final do capítulo.
FileOut visto anteriormente, outro mecanismo para arquivamento e carga
de código. Este mecanismo, também conhecido como Parcel possui Boa parte das ferramentas de suporte e exemplos fornecidos Adicionando
várias vantágens sobre o anteriormente estudado. Discutiremos agora junto com a distribuição do VisualWorks vem em forma de parcel. Existe um novo
algumas destas vantágens, mas tenha em mente que para pequenas uma maneira rápida de carregalos para sua imagem. Selecione o item de parcel à sua
parcelas de código ou até mesmo para se salvar rápidamente o trabalho menu <Tools> >> <Load Parcel Named...> a partir do VisualLaucher. imagem
do dia, o mecanismo de FileIn e FileOut é muito bom. Todos os parcels que estiverem nos diretórios de perquisa de parcels
(que podem ser especificados a partir da janela de settings) serão lista-
Poderiamos definir parcels como sendo um mecanismo para sal- dos em uma janela. Selecione os que você deseja carregar e em seguida
var e carregar rapidamente código em Smalltalk. Parcels também são uti- aperte o botão OK. Existe um botão SelectAll, mas aconcelhamos forte-
lizados para distribuição de aplicações devido a sua facilidade de mente que não o apertem pois todos os parcels que se encontram nos
controle de código e versões. A principal diferença entre parcels e FileIn/ diretórios de pesquisa serão adicionados a sua imagem. Esssa tarefa
FileOut é que os parcels nos permitem salvar o código executável, ou pode tomar algumas dezenas de minutos. A figura 3.24 mostra a janela
seja o bytecode, de nossa aplicação em um arquivo separado da ima- para seleção e carga de parcels. A lista de parcels apresetada contém
gem e também permite que salvemos o código fonte. Embora parcels todos os que Smalltalk encontrou nos diretórios de parcels declarados na
nos permitam salvar parcelas de código executável separadamente eles janela de Settings, descrita anteriormente.
terão necessáriamente que ser carregados em uma imagem para que
possam ser executados.

Código fonte Arquivos contendo o código executável são salvos com a exten-
e código ção .pcl, e arquivos contendo o código fonte são salvos com a extenção
executável .pst. O VisualWorks fornece um tipo de browser especial para que geren-
ciemos nossos parcels. Na figura 3.23 temos os 3 botões para aciona-
mento dos browsers fornecidos pelo VisualWorks. O browser de parcels
pode ser acionado pelo botão da direita.

Figura 3.23 Botões para abertura dos browsers de Parcels

Figura 3.24 Janela para carga de novos parcels

66 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 67


Conceitos Básicos do Ambiente Geração de Pacotes de Programa: Parcels

Removendo O processo de remoção de um parcel presente em sua imagem


um parcel e similar ao processo de carga. a partir do menu principal do visualLau-
cher selecione o item <Tools> >> <Unload Parcels Named ...>. Uma
janela será aberta apresentando todos os parcels carregados em sua
imagem, conforme representado na figura 3.25 na página 68. Selecione
os parcels que você deseja remover e então pressione o botão OK.

Figura 3.26 Browser para criação e gerenciamento de parcels

Figura 3.25 Janela para remoção de parcels necessárias foram adicionadas ao parcel, faz-se necessário salvá-lo.
Isso pode ser feito através do item de menu <Parcel> >> <Save>.
Criando seu Criar um parcel é um passo essencial para o desenvolvimento e O Parcel Browser adota algumas convenções que indicam o
próprio intercâmbio de suas aplicações e, ao contrário do que possa parecer, é estado do código fonte em relação a um parcel. A tabela 3.1 na página
parcel bem simples. Abra um parcel Browser (como mostrado anteriormente 70 detalha algumas delas.
neste capítulo) e selecione a partir do menu principal do browser o item
<Parcel> >> <New>. Uma janela será aberta pedindo que você indique o
nome do parcel a ser criado. A seguir navegue pelas classes protocolos
e métodos adicionando os que pertencem a aplicação que queremos sal-
var no parcel que acabamos de criar. Note que se adicionarmos uma
classe a um parcel todos os seus protocolos e métodos serão automati-
camente adicionados ao parcel, e se adiocionarmos um protocolo a um
parcel todos os métodos por ele agrupados serão adicionados ao par-
cel.Uma vez que o todas as classes, métodos, protocolos e variáveis

68 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 69


Conceitos Básicos do Ambiente Código Executável

convenção significado
3.16 Código Executável
Negrito Indica que existe algum subitem adicionado ao parcel.
Sublinhado Indica que todo o item foi adicionado ao parcel. Ao contrário de alguns ambientes de desenvolvimento de JAVA,
que permitem que você gere código nativo executável para a máquina
indica itens definidos em mais de um parcel. Representa
Vermelho específica onde você desenvolveu a sua aplicação, nenhuma implemen-
possivel conflito.
tação de Smalltalk permite que código executável seja gerado. Este
* Indica que o parcel foi modificado e ainda nao foi salvo código JAVA “nativo” evidentemente perdeu as características de inde-
< Indica que o parcel nao foi criado mas sim carregado pendência de sistema operacional e de máquina que são características
o parcel possui parte de seu código que não está pre- essenciais da linguagem JAVA. Smalltalk utiliza outra filosofia para con-
!
sente na imagem. tornar o problema de aplicações “prontas” para o usuário usar, sem a
o parcel possui métodos que foram sobrescritos durante necessidade de instalar máquina virtual e outras coisas. Veremos isto
+ neste capítulo.
seu processo de carregamento.
Tabela 3.1 Convenções adotadas pelo parcel browser Desta forma, o que foi durante muito tempo muito comum de se
ver em relação a Smalltalk, é que ele era muito utilizado como ferramenta
Alguns Workspace Organizer -- Este é um parcel muito útil pois funci- de prototipação devido às óbivias vantagens oferecidas pelo mesmo
parcels ona como um ficheiro de workspaces, onde vários itens e subitens são nesta tarefa, mas dificilmente era utilizado como ferramenta para criação
comumente podem ser criados a maneira de um menu permitindo organizar o seu de produtos. Diante deste quadro, vários esforços tem sindos dispendi-
utilizados código de teste. dos no sentido de se criar aplicações executáveis a partir de uma aplica-
ColorEditing -- Permite que se defina cores para variáveis, ção escrita em Smalltalk.
métodos, classes, etc. Muito útil durante o desenvolvimento. Este tipo de
caracteristica adicionada por este parcel está presente na maioria dos Em Microsoft Windows, VisualWorks fornece uma ferramenta Criando
ambientes de desenvolvimento modernos. chamada ImageMaker para minimizar este problema. O que ela faz na aplicativos
realidade é “limpar“ a imagem de todos os objetos que sejam irrelevantes .exe
VisualWave -- Permite que aplicações sejam publicadas na
a sua aplicação deixando a mesma compacta. Em seguida ele junta a
Internet. Na realidade faz uma tradução da aplicação para HTML.
imagem com uma versão igualmente enxuta da máquina virtual e salva o
ODBC -- Permite acesso a bancos de dados utilizando o meca- resultado final com uma extensão .exe. O arquivo final geralemente tem
nismo de ODBC. seu tamanho girando em torno de 5 MB e não possui a mesma perfor-
DLL & C Connect -- Permite que código objeto salvo sob a mance que um programa compilado, pois em verdade será interpretado.
forma de bibliotecas executáveis em DLLs (Windows) e em arquivos .SO
(Unix e Linux) sejam acessados dentro do Smalltalk. Esta ferramenta Existe uma segunda abordagem. Trata-se de traduzir o código Convertendo
quando bem utilizada pode permitir um aumento de perfornance nas apli- escrito em Smalltalk para C++, permitirndo desta forma que o código seja Smalltalk
cações que utilizem muito processamento. compilado de forma bem eficiente. Este enfoque é útil dentro de uma filo- para C++
sofia de se utilizar as facilidades de prototipagem de Smalltalk para o
desenvolvimento de uma aplicação, que, depois de pronta, é cross-com-

70 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 71


Conceitos Básicos do Ambiente Gerenciando o Arquivo de Alterações

pilada para uma linguagem mais rápida. Uma ferramenta para isto já
existia nas versões 2.5 a 4.0 do ObjektWorks Smalltalk, que podia ser 3.18 Gerenciando o Arquivo de Alterações
adquirido juntamente com um pacote (somente disponível para ambien- O arquivo .cha apresentado anteriormente funciona como um log
tes Apollo Domain e Unix) denominado ObjektKit C++. O ObjektKit dispo- de todas as atividades do programador durante o processo de programa-
nibilizava versões C++ de todas as classes básicas do Smalltalk (com ção do VisualWorks. Tudo, desde a criação de uma classe até a posição
limitações) e vinha com um conjunto de classes cross-compiler para você do browser na tela é registrado e arquivado neste arquivo.
transformar o código Smalltalk que você desenvolveu em código C++,
que podia então ser compilado em um ambiente de desenvolvimento Desta forma, ele se torna uma ótima referência para restauração
C++ similar ao SystemBrowser. A dificuldade de uso deste ambiente e as da imagem no caso de algum problema como o computador travar, a luz
limitações das classes C++ que “imitavam” as classes Smalltalk fizeram acabar ou o programador perfazer algo inimaginável.
a ParcPlace descontinuar o produto em 1992. A partir do VisualLaucher existe um ítem no menu chamado
Hoje em dia existe SPICE, que é um ambiente experimental para <Changes>. Seus subitens nos permitem manipular arquivos .cha e mui-
a conversão de código Smalltalk para C++. SPICE é um projeto de pes- tos outros tais como .pcl .st etc. Se nada ocorrer de anormal, não existe a
quisa e sua utilização é exclusivamente acadêmica. necessidade de se utilizar as ferramentas de manipulação de alterações,
mas caso o leitor sinta necessidade de saber como elas funcionam, con-
sulte a referência bibliográfica ao final deste capítulo.
3.17 Help do VisualWorks
VisualWorks é extremamente estável, mesmo a versão para Restaurando
Informações sobre Smalltalk e VisualWorks não são muito fáceis Microsoft Windows, e você dificilmente vai se encontrar em uma situação código e
de encontrar. não existe nenhum livro em portugues (além deste) e os onde há um error de acesso à memória ou outro que faça a máquina vir- instâncias
poucos que existem em ingles só cobrem até a versão 3 do VisualWorks. tual cair. Mas isso não é completamente impossível e sempre há as situ- após a queda
Na internet existem alguns sites bons (que listaremos ao final do livro), ações onde houve falta de energia durante uma sessão de edição ou do sistema
mas se o leitor se aventurar pelo altavista procurando a ermo, o que você saiu sem salvar o arquivo imagem. É possível restaurar o estado do
encontrará serão muitos sites superficiais e contendo crasos erros con- imagem, ou os método que foram editados foram perdidos ?
ceituais. Smalltalk, como foi dito, realiza um log de tudo o que você faz e
O help do VisualWorks é uma cópia resumida dos manuais mas o código de todos os metodos que você alterou através de <<accept>>
para uma consulta rápida ele se mostra bem eficiente. No caso do leitor fica registrado no arquivo de alterações .cha, mesmo que você não tenha
desejar uma explicação mais detalhada de alguma classe, existe uma salvo o imagem. Se você quiser restaurar o estado de seu imagem,
opção no system browser que mostra o comentário da classe. Todas as mesmo instâncias que foram criadas, tudo o que você precisa fazer é
classes da biblioteca de classes contém uma descrição. Elas podem ser reexecutar os comandos ou as alterações de código-fonte protocoladas
acessadas através do ítem de menu <View> >> <Comment>. Também no arquivo .cha. Suponha que você tenha iniciado uma sessão de desen-
podemos verificar os comentários das classes através de <Help> >> volvimento e tenha criado uma categoria “Teste”, onde você acabou de
<Object reference>. criar uma classe Teste como subclasse de ApplicationModel, conforme
mostrado na figura 3.27 .

72 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 73


Conceitos Básicos do Ambiente Exercícios

se refere ao comando de salvamento do imagem (com a data do salva-


mento) e as outras duas se referem ao processo de criação da classe
que descrevemos anteriormente. Para recuperar uma ou mais modifica-
ções, clique em alguma modificação e ative o menu de opções. Lá há
varias opções, desde refazer a modificação específica selecionada, até
eliminar todas as modificações, como mostrado na figura 3.28 .

Figura 3.27 Classe Teste recém criada, com as variáveis de instância a, b e c.

No momento em que você havia terminado de realizar a criação


desta classe e você estava pensando se isa salvar o arquivo imagem ou
não, houve um corte momentâneo de energia e o computador desligou-
se. Como fazer para recuperar o código que você digitou ?
Para recuperar o que digitou, você deve reiniciar o seu arquivo
imagem e imediatamente ir para o ponto de menu Changes >> Open Figura 3.28
Change List. Uma janela denominada Change List vai abrir. Uma vez
aberta esta janela, vá para o ponto de menu File >> Recover Last Chan-
ges. A opção recuperação das últimas mudanças abre o arquivo .cha e 3.19 Exercícios
busca lá todas as modificações protocoladas desde a última vez que o
arquivo imagem foi salvo. No nosso caso você vai ver o que esta repre- 1. Que características, boas e ruins, o smalltalk possui devido ao fato de
sentado na figura 3.28 : uma lista de três modoficações, onde a primeira ser interpretado e não tipado?

74 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 75


Conceitos Básicos do Ambiente

&RQFHLWRV%iVLFRV
2. Abra a imagem visualnc.im e salve-a com outro nome.
3. Tente abrir outro VisualLaucher programacionalmente a partir do Capítulo 4
workspace.
4. Procure referências sobre o Transcript o help e tente enviar algumas
mensagens ao Transcript a partir do workspace. GD/LQJXDJHP
5. Utilize o mecanismo de busca de classes para encontrar as seguintes
classes:
OrderedCollection
Object
Point
ArraySet
(obs: Tente utilizar * e ? durante as pesquisas)
6. Crie uma categoria como apresentado anteriormente neste capítulo.
Crie em seguida uma classe chamada Fatorial, então crie o pro-
tocolo “aritimetica“ e adicione o método ‘fat: num’.

(obs: por enquanto apenas crie, no capítulo seguinte escreveremos o Este capítulo tem por objetivo apresentar ao leitor o básico da lin-
método, mas caso o leitor sentir vontade de tentar...). guagem Smalltalk. Inicialmente abordaremos o conceito de classes e obje-
7. Digite as seguintes parcelas de código no Workspace e inspecione-as tos visto pela ótica do Smalltalk. Em seguida discutiremos todos os
(use a opção inspect it). Verifique o que aparece no lado direito da mecanismos de orientação a objetos disponíveis, falaremos um pouco
janela de inspeção. Essa saída é criada pelo método printOn:. sobre a biblioteca de classes e sobre a filosofia de programação, apresen-
1) 10 taremos a sintaxe e características específicas da linguagem, discutiremos
2) 10.12 o conceito de namespaces e, por último, apresentaremos alguns objetos
3) Rectangle origin: 10@10 corner: 100@100 básicos e que são extensivamente utilizados durante o processo de pro-
4) |c| gramação.
c := OrderedCollection new.
c add: 10;
add: 20;
add: ‘st-80’. 4.1 Orientação a Objetos
c. Smalltalk é uma linguagem OO dita pura. Como apresentado no
8. Acompanhando a distribuição do Smalltalk vem uma série de parcels histórico da linguagem, podemos concluir que se trata da linguagem-mãe
e arquivos st de exemplos que podem ser facilmente carregados em do paradigma orientado a objetos e que influenciou todas as demais lin-
sua imagem. Consulte o help online (acessível através do Visual- guagens OO.
Laucher) e carregue alguns destes parcels. Isso lhe ajudara a se
familiarizar com a maneira como código em Smalltalk é escrito. O importante para o leitor (principalmente se o leitor já está famili-
arizado com alguma outra linguagem de programação OO), é notar e

76 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Conceitos Básicos da Linguagem Orientação a Objetos

registrar as diferenças entre os conceitos de orientação existentes em mente identificar uma dada instâncias como pertencente a uma certa
Smalltalk e outras linguagens tais como C++ e Object Pascal. Podemos classe mas sim permitir algumas otimizações em termos de espaço e
afirmar que os conceitos de OO em Smalltalk são simples. Perto dos performance que serão explicadas logo a diante.
detalhes existentes em C++ referentes a OO, Smalltalk pode parecer a Classes e Instâncias são conceitos tão primários em Smalltalk
primeira vista um tanto quanto simplória. Porém isso não é verdade. A que nos reportarmos a eles ainda divenças vezes durante o resto do
riqueza de expressividade em Smalltalk resize na seu alto grau de orto- livro, desta forma a não compreensão do conceito em sua plenitude
gonalidade1 e principalmente no fato de que absolutamente tudo em neste momento não deve preocupar o leitor.
Smalltalk são objetos.
Uma classe em Smalltalk além de ser um molde para a criação Classes
Classes x Para o leitor que ainda não está familiarizado com os conceitos de instâncias também é por si só um objeto. Isso pode parecer um tanto
instâncias de orientação a objetos, faz-se necessário uma clara definição e distin- quanto confuso a primeira vista, mas o que temos que tem sempre em
ção dos conceitos e nomenclatura que permeiam este paradigma de pro- mente quanto tratamos de Smalltalk é que tudo dentro de sua imagem
gramação. Caso o leitor já esteja familiarizado com tais conceitos, deve são objetos.
sentir-se à vontade para pular os próximos tópicos, no entanto, sugeri-
mos que sejam revistos, devido às nuâncias e pequenas diferenças aqui Uma pergunta pode estar perscrutando o leitor: Mas se até
apresentadas. mesmo uma classe em Smalltalk é um objeto, quem é a forma para cria-
ção de classes? A resposta, seguindo a regra básica de que tudo em
A seguir introduziremos brevemente o conceito de classes e ins- Smalltalk são objetos já deve ser imaginada. Obviamente um objeto.
tâncias, apresentaremos sua correlação e nas próximas seções deste Este objeto chama-se metaclassse e cria um mecanismo reflexivo que
capítulo descreveremos em maiores detalhes cada uma delas. permite ao Smalltalk adotar esta forma de mecanismo2.
Uma classe pode ser vista como um molde para a criação de Deixando um pouco de lado esta discussão sobre metaclasses
objetos/instâncias. Embora uma classe em Smalltalk não seja propria- visto o sua ínfima influencia para ações práticas de desenvolvimento
mente apenas um molde de criação, é importante que este conceito fique vamos entender como uma classe está organizada. Ela possui, exata-
registrado, e uma maior explanação do mesmo poderá ser encontrada mente como os objetos atributos, e métodos. Também está sobre a regra
mais a frente. do encapsulamento que dita que todos os seus atributos não podem ser
Uma instância/objeto é um conjunto de atributos (características acessados de fora da classe e todos os seus métodos são visíveis a
do objeto) e mensagens (que permite ao objeto perfazer ações úteis) qualquer um. Em geral, quando nos referimos a métodos e atributos de
agrupados todos sob uma “casca“ que os isola do resto do mundo. A uma classe falamos em variáveis de classe e métodos de classe.
este isolamento, dá-se o nome de encapsulamento. Uma classe não precisa e nem existe maneira de ser instanci-
Instâncias são criadas a partir de classes, e mantém uma refe- ada, ela é simplesmente criada. Seus atributos uma vez alterados per-
rência a sua classe criadora. O motivo desta referência não é unica- manecem com o novo valor até que eles sejam alterados novamente e

1. ortogonalidade é a capacidade que uma linguagem de programação tem de combinar


suas construções com seus tipos de dados. 2. Existe um ótimo artigo sobre metaclasses, sua referência está na bibliografia.

78 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 79


Conceitos Básicos da Linguagem Orientação a Objetos

mesmo que a imagem seja fechada eles continuarão a armazenar o valor vel suportado que será discutida em detalhes no capítulo relativo à variá-
setado, desde claro que a imagem tenha sido salva previamente. veis.
Programar em Smalltalk consiste fundamentalmente em se criar
e refinar classes. As ferramentas utilizadas para a criação e edição de Instâncias de uma classe ou objetos que em verdade tratam do Instâncias
classes são os browsers. Daí a grande necessidade de se familiarizar mesmo conceito, são criados através do envio de uma mensagem de cri-
rapidamente com o seu funcionamento. Caso o leitor ainda não se sinta a ação a sua classe molde. Esta mensagem geralmente é new. Existe
vontade com o browser, reporte-se quantas vezes for necessário ao capí- alguns casos de objetos especiais também conhecidos como objetos lite-
tulo anterior. rais em que a instanciação se dá diretamente. Objetos literais serão
abordados em detalhes neste capítulo. Possuem mensagens e atributos
e são geralmente descritos como métodos me instâncias e variáveis de
instância. Estão como já dissemos sob a regra do encapsulamento e
podem ser criados a qualquer momento.
Como sabemos, instâncias de uma determinada classe pos-
suem atributos e respondem a mensagens através da execução de
métodos. Estes métodos por sua vez são parcelas de código que são
executados. Desta forma poderíamos imaginar que toda vez que uma
instância fosse criada, todo o código relativo aos seus métodos fosses
copiados também para o espaço de memória a ela destinado. Mas como
as instâncias são idênticas umas as outras em sua estrutura diferindo
apenas no valor de seus atributos, podemos ver que essa abordagem da
cópia de código a cada instância criada seria um grande desperdício de
espaço. Em verdade a Smalltalk não replica código a cada instância cri-
ada. Como já havíamos citado, quando uma instância é criada ela tam-
bém cria uma referência à sua classe fonte, desta forma e guarda como
um atributo especial, uma relação de todas as mensagens que ela
Figura 4.1 System Browser e opções classe, instância e variáveis compartilhadas conhece diretamente, ou seja que foram implementados na sua classe
criadora. Quando ela recebe uma mensagem, uma pesquisa é execu-
Na figura 4.1 vemos o System Browser, descrito no capítulo tada nesta lista de mensagens conhecidas, caso a mensagem recebida
anterior. Na terceira janela da esquerda para a direita vemos três botões conste na lista, uma requisição é enviada a classe fonte e o método cor-
de seleção. Dependendo de qual estiver selecionado, as informações respondente a mensagem recebida é executado. No caso da mensagem
apresentadas pelas janelas de protocolos e métodos do system browser, não constar na lista de mensagens implementadas na classe fonte, ela
mudam. Caso o botão instance esteja selecionado todos os protocolos e não é refutada diretamente, porém este segundo caso será apresentado
métodos relativos a instâncias serão apresentados, e em caso da sele- no momento em que explicarmos o mecanismo de herança e a hierar-
ção ser class os protocolos e métodos de classe serão apresentados. A quia de classes.
terceira opção, shared variables, diz respeito a um tipo especial de variá-

80 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 81


Conceitos Básicos da Linguagem Polimorfismo

porque de maneira análoga a forma que uma instância mantém uma


4.2 Mecanismo de Herança e Hierarquia de referência a sua classe criadora, toda subclasse mantém uma referência
Classes a sua superclasse.
Herança é o processo pelo qual uma classe herda característi-
cas e funcionalidades de outra classe. Desta forma é criada toda uma AritimeticValue
hierarquia de classes baseada no mecanismo de herança que de sim
não
maneira incremental aumenta o poder de expressividade das classes implementa
mais especializadas e minimiza o custo e tempo de desenvolvimento ‘negative’?
para a criação de novas classes. Este mecanismo também permite um
maior grau de reutilização de código sendo uma das grandes vantagens
da abordagem OO sobre a abordagem estruturada tradicional. Uma executa método
Number sim
implementa ‘negative’
explicação mais detalhada sobre herança foge do escopo deste livro, e ‘negative’?
sugerimos fortemente ao leitor consultar a bibliografia ao final deste capí-
não
tulo caso o conceito de herança lhe seja novo.
Existem a priori dois tipos de herança que são adotados dentre
sim
todas as linguagens OO disponíveis: A herança simples e a múltipla. Integer
Smalltalk adota a herança simples, e ao contrário de linguagens como
C++ onde existem operadores3 que definem quais partes da classe pai implementa mensagem ‘negative’
devem ser herdadas, todo o conteúdo da classe pai sempre é herdado ‘negative’?
pela classe filha.
Voltando agora ao esquema discutido na seção anterior sobre a 124752
identificação de uma mensagem e sua posterior execução. Tínhamos
parado no momento em que uma mensagem não era identificada como
válida na lista de mensagens conhecidas pela instância que a recebeu.
Neste caso, a pesquisa sobe um grau na hierarquia de classes, ou seja, Figura 4.2 Mecanismo de execução de uma mensagem
pesquisa se a mensagem é conhecida pela classe pai a classe que criou
a instância, em caso afirmativo, o código referente aquela mensagem é
executado, em caso negativo, a pesquisa sobe mais um nível na hierar- 4.3 Polimorfismo
quia e continua este esquema até a mensagem ser validada ou até che-
O conceito de polimorfismo também é suportado em Smalltalk.
gar ao todo da hierarquia. Somente neste caso um erro é gerado. Essa
Segundo o polimorfismo, classes distintas podem ter métodos de mesmo
pesquisa em seqüência ascendente na hierarquia de classes é possível
nome. Isso permite por exemplo que tanto a classe Passaro quanto a
classe Aviao possuam o método “voe“. Essa facilidade permite-nos apli-
3. Em C++ podemos utilizar as palavras reservadas public, protected e private para
definir quais partes da classe pai serão herdadas pela classe filha.

82 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 83


Conceitos Básicos da Linguagem Características da Linguagem

car várias técnicas como por exemplo padrões e facilita o entendimento No capítulo anterior citamos que a linguagem não gera um pro- Caracterís-
da estrutura de uma classe. grama executável. Em verdade isso acontece devido ao fato da lingua- ticas funcio-
gem ser interpretada. Uma linguagem ser interpretada significa que ao nais
compilarmos um programa (no caso do Smalltalk isso acontece toda vez
4.4 Métodos, mensagens e variáveis que selecionamos a opção accept) o compilador não gera instruções de
máquina, mas sim um código intermediário, código esse que chamamos
Método, mensagem e variável são três conceitos centrais em de ByteCode. Existem outras linguagens que também interpretam código
Smalltalk e bastante complexos e que necessitam de grande detalha- intermediário pré-compilado e organizado em bytecodes. Podemos citar
mento. Para apresentar ao leitor todas as nuâncias e detalhes pertinen- JAVA como a mais famosa de todas.
tes a estes conceitos, capítulos específicos foram escritos.
Quando compilamos um programa, instruções de máquina são
No Capítulo 5 deste livro tratamos de mensagens e métodos, geradas e estamos tornando o programa dependente da máquina que o
dois temas em Smalltalk tão intimamente ligados, que se confundem. executará, pois as instruções assembly que processadores da Intel reco-
No Capítulo 6 deste livro trataremos de variáveis em Smalltalk. nhecem são diferentes das instruções reconhecidas pelos processado-
Em Smalltalk toda variável é uma referência a um objeto, independente- res SPARC. Desta forma, gerando um código intermediário (ByteCode)
mente da complexidade deste, podendo ser apenas um Byte ou um tornamos nossos programas independentes da plataforma que os execu-
objeto extremamente complexo, representando todo o mecanismo de fin- tará, bastando para alcançar esta independência escrevermos interpreta-
cionamento de uma central hidrelétrica. Esta característica de Smalltalk dores específicos para cada máquina. Estes interpretadores são
‘we muito diferente das outras linguagens e porisso abordaremso variá- chamados de máquinas virtuais.
veis em um capítulo à parte. Outra característica interessante de Smalltalk é que a linguagem
não é tipada. Isso significa dizer que ao definirmos uma variável não pre-
cisamos dizer qual tipo de dado aquela variável poderá armazenar. Isso
4.5 Características da Linguagem provoca uma maior flexibilidade ao programas visto que as variáveis
poderão armazenar qualquer valor (no caso objetos) em momentos dis-
Como toda linguagem de programação, Smalltalk possui várias
tintos.
características relativas ao funcionamento da linguagem bem como à
forma como devemos escrever nossos programas. Como já dissemos, escrever programas em Smalltalk consiste
fundamentalmente em criar e editar classes. Criamos classes através de
De uma maneira geral podemos dividir tais características nos
um template como mostrado no capítulo anterior e de maneira análoga
seguintes sub-grupos:
criamos os métodos. Para tornar qualquer criação ou alteração válida
• características funcionais - relativas a como a linguagem precisamos aceitar nossas alterações. Isso é feito através de um popup
funciona. menu selecionado a partir do botão direito do mouse. O item de menu
• características léxicas - definem como os identificadores, ou responsável por este processo é accpet. Ele compila o código a ser
seja, métodos, variáveis, classes, etc, devem ser escritos. Sua
aceito e posteriormente o salva. desta forma, não existe em Smalltalk um
forma léxica.
operação específica para compilar código fonte como na maioria das
outras linguagens. Citamos esta característica da linguagem aqui por ser

84 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 85


Conceitos Básicos da Linguagem Filosofia de programação

bem diferente e também porque identificamos o processo de compilação Na tabela 4.2 apresentaremos algumas das convenções utiliza-
como uma das principais dúvidas existentes entre os programadores que das. Aqui as apresentaremos de maneira simplificada, cobrindo-as em
começam a aprender esta linguagem. maiores detalhes nos capítulos seguintes.

Caracterís- Com relação as características léxicas, ou seja, como os progra- identificador convenção exemplo
ticas léxicas mas em Smalltalk podem ser escritos, quais nomes de variáveis, méto- classes primeira letra em Maiúscula e a Carro
dos, classes, etc, são válidos, Smalltalk se mostra extremamente flexível. cada nova palavra também. Não se
Nas próximas linhas apresentaremos as poucas regras existen- usa _.
tes com relação a como é permitido escrever identificadores e quais as métodos primeira letra em Minúsucla e a trocaPneu
convenções adotadas pela biblioteca de classes. cada nova palavra uma maiúsula
iniciando. Não se usa _.
Com relação a que caracteres podemos utilizar para a criação
de nossos identificadores, sejam eles nomes de classes, métodos e vari- variáveis de instan- primeira letra em Minúsucla e a pneuReserva
cia cada nova palavra uma maiúsula
áveis, podemos utilizar os seguintes caracteres:
iniciando. .
a b c d e f g h i j k l m n o p q r s t u v variáveis de classe primeira letra em Maiúscula e a TipoPneu
x y z A B C D E F G H I J K L M N O P Q R S T U V cada nova palavra também.
X Y Z 1 2 3 4 5 6 7 8 9 0 _
NameSpaces sem restrições.
Também podemos utilizar qualquer símbolo de acentuação. A Categorias cada palavra inicia-se com maiús- Veículos-4Rodas
seguir apresentaremos alguns identificadores aceitos: cula. Pode-se usar - e _
estáRodando Protocolos tudo minúsculo. Pode-se usar - e _ initialize-release
_comendo Tabela 4.2 Convenções de nomeação em Smalltalk

enquanto_verdade Conhecer e seguir estas convenções além de facilitar nosso


entendimento de como as bilioteca de classes está escrita e funciona,
Como restrição à declaração de identificadores existe a impossi-
também devido a regularidade pelas convenções conferidas torma muito
bilidade de iniciá-los com número, deta forma declarar uma variável
mais simples encontrar características específicas de que por ventura
como “4Clues”, gerará um erro. Isso acontece pois na sintáxe de núme-
necessitemos durante o processo de programação.
ros, como veremos mais a diante, podemos utilizar algumas letras para
representar bas e exponenciação.
Também se faz necessário citar que a linguagem é case sensi-
4.6 Filosofia de programação
tive, ou seja, a linguagem faz diferenciação entre letras maiúsculas e
minúsculas, desta forma ‘ehVerdade’ e ‘EHVerdade’ são para Small- Programar em Smalltalk não consiste simplesmente em se
talk indentificadores distintos. escrever o código fonte definindo classes, instanciando objetos e execu-
tando-os.

86 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 87


Conceitos Básicos da Linguagem Filosofia de programação

Diferentemente de outras linguagens de programação onde mos que estes são os passos comuns que nós os autores utilizamos
escrevemos programas em forma textual e em seguida o submetemos à quando estamos programando e também tem surtido bom efeito no
um compilador para que erros sejam depurados e, ao fim de todo o pro- aprendizado da linguagem em cursos por nós ministrados.
cesso de depuração, um programa objeto seja gerado, em Smalltalk Os três passos por nós sugeridos são:
vemos uma maior interatividade, onde os programas são escritos, depu-
• Navegar
rados e executados de maneira concomitante.
• Editar/Criar
Diante desta abordagem de programação, bem como as facilida- • Inspecionar
des fornecidas pela não tipagem e também devido a ela ser interpretada,
podemos imaginar que Smalltalk seja uma linguagem muito boa para Como a biblioteca de classes e bem grande (algumas milhares Navegar
prototipação. Isso é verdade. A experiência mostra que o tempo de pro- de classes e algumas dezenas de milhares de métodos), se torna prati-
topitação em Smalltalk é extremamente menor se comparado ao tempo camente impossível sabermos exatamente que classe contém tal funcio-
gasto em outras linguagens de programação. nalidade e qual específicamente é o método desejado. Desta forma
Mas não é só neste aspécto que Smalltalk se mostra singular em devemos contantemente nos reportar à biblioteca de classes a procura
termos da maneira de se programar. Como sabemos, a linguagem é dita da funcionalidade desejada. O system browser possui a forma apresen-
orientada à objetos pura. Isso significa que como tudo nela são objetos, tada no capítulo anterior exatamente por causa desta necessidade de
características como reutilização de código e objetos sejam plenamente pesquisa constante. Desta forma se queremos saber se existe alguma
utilizadas. Programar em Smalltalk pode então ser visto mais ou menos função de exponenciação para números em ponto flutuante devemos
como bricar com um jogo de LEGO. Isso para aqueles que vêem a pro- executar uma pesquisa. Esta perquisa é facilitada então pela forma como
gramação como algo divertido e prazeroso. o system browser está organizado. Como sabemos que um pontos flutu-
antes são números temos uma indicação de que devemos procurar na
Além disso, a biblioteca de classes é extremamente madura,
parte referente a números da hierarquia de classes. Esta está sobre a
tendo cerca de 30 anos, podemos imaginar que ela seja extremamente
categoria Magnitude-Number. Assim fica fácil passearmos pelas classes
completa e útil, desta forma boa sempre que precisamos de alguma fun-
e métodos desta parte da hierarquia de classes e encontrarmos o
cionalidade em nossos programas devemos primeiro verificar a biblioteca
método ‘**’ .
de classes para ver se ela já não existe.
É muito comum os iniciantes no aprendizado de Smalltalk dize- Uma vez que não pairarem mais questões tais como se existe tal Editar/Criar
rem que a linguagem é complicada e que eles não conseguem criar pro- funcinalidade e de como podemos utiliza-las passamos para o passo em
gramas nela. De fato, as primeiras investidas de programação são um que devemos criar nossas classes e métodos.
tanto complicadas, pois para produzir programas em Smalltalk se faz
necesário conhecimento de que classes existentem na biblioteca de clas- Note que durante todo o processo de edição/criação podemos
ses e de como podemos utiliza-las. voltar a navegar pelas classes a procura de um funcionalidade ao para
sanar qualquer dúvida.
Diante deste quadro fornecemos uma filosofia de programação
dividida em 3 passos que devem ser seguidos para facilitar o programa-
A medida que vamos criando nossas classes e métodos pode- Inspecionar
dor novado em Smalltalk a produzir programas. Em verdade, observa-
mos verificar se elas estão correspondendo ao que desejamos. Desta

88 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 89


Conceitos Básicos da Linguagem Números

Figura 4.4 Janela de inspeção contendo os dados relativos a um número

Figura 4.3 Definição do método “**” na classe Number 4.8 Números


Quase todos os tipos de números são suportados em Smalltalk
forma podemos inspecioná-las em sua execução. Para isso podemos uti-
sobre a forma de literais. Existem inteiros, ponto flutuante e frações .
lizar a opção inspect que, como mencionamos no capítulo anterior, for-
Todas as classes relativas aos números literais aqui apresentados se
nece-nos uma janela mostrando o estado intermo dos objetos.
encontram organizadas sob a categoria Magnitude-Number, desta forma,
Note que podemos inspecionar praticamente tudo em Smalltalk. sinta-se a vontade para navegar por esta parte da hierarquia de classes
Desde um simples número até mesmo o browser que utilizamos para para aprender mais sobre como os números funcionam em Smalltalk.
criar nossas aplicações.
Os números inteiros são criados apenas sendo digitados. Desta SmallInteger,
forma, ao digitarmos 123 estaremos criando uma instancia da classe LargePositive-
4.7 Objetos especiais - Literais SmallInteger. A seguir apresentamos anguns exemplos de números Integer e
inteiros, que também são conhecidos na matemática como números LargeNega-
Existem alguns objetos em Smalltalk que devido a sua grande tiveInteger
naturais.
utilização possuem algumas facilidades em se tratando do processo de
sua criação. A tais objetos damos o nome de objetos literais. 123
A seguir discutiremos os objetos literais suportados pelo Visu- -2003
alWorks apresentando algumas de suas facilidades. 1237618231873777777713781623981763176331231
2318971238123791273192387123982739238712938712937

90 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 91


Conceitos Básicos da Linguagem Números

1298754609685407983876487236443489470958694567368 É interessante notar que podemos utilizar tanto “d“ como “D“
74564385468573235284385623856293485 para indicar que tal número é do tipo doublee também não é necessário
Como podemos ver no útimo exemplo citado, Smalltalk suporta utilizar escrever a parte fracionária do número caso ela seja zero.
números de tamanhos extremamente grandes. Na verdade não existe
um limite prático para qual o tamanho máximo um número inteiro pode Números fracionários podem ser criados digitando-se numera- Fraction
ter, o que acontece é que para números entre -536870912 e 536870911 dos/denominador. Note que se o resultado da divisão entre as partes
serão instancias da classe SmallInteger e para os demais inteiros tere- envolvidas for inteiro a um inteiro será gerado.
mos instanicas de LargePositiveInteger e LargeNegativeInteger. Por exemplo, se digitarmos 10/2 o SmallInteger 5 será gerado,
porém se digitarmos 10/3 uma instancias de Fraction é que será criada.
Float e Números em ponto flutuante, também conhecidos como con-
Double junto dos números reais na matemática, são representados em Smalltalk Podemos representar qualquer número também com relação a Números em
utilizando um ponto “.“ para separar a parte inteira da parte fracionária. A sua base. Base de um número indica qual o sistema numérico utilizado. outras bases
seguir apresentamos alguns exemplos: Dentre os mais utilizados temos o decimal que também é o padrão, o
120.0 binário e o hexadecimal. Porém Smalltalk nos permite utilizar qualquer
base numa faixa que vai de 2 ate 36. A forma de representação de núme-
-12121212.0123 ros em outras bases que não sejam a decimal é a seguinte:
Note que não é permitido escrever números em ponto flutuante <base> r <número>
omitindo-se nem a parte inteira nem a fracionária. Desta forma, 100.
implicará em se criar apenas um inteiro e seu programa ainda estará Quando tratamos de bases que possuam mais que dez dígitos,
sucetível a erros, pois o caracter “.“ também é utilizado como delimitador apenas os algarismos arábicos não são suficientes para representar
de comandos. todos os dígitos suportados pela base. Por exemplo se utilizarmos uma
base de dezesseis dígitos como no caso dos números hexadecimais, uti-
Existe um limite para números do tipo float.Eles devem estar lizamos os seguintes caracteres para representar cada um dos possíveis
dentro da faixa que vai de -1038 a 1038 . Caso necessitemos de uma pre- dígitos:
cisão maior podemos utilizar números do tipo double. Eles podem variar
em uma faixa que vai de -10307 a 10307 e são declarados exatamente
como os números em ponto flutuante porem sendo finalizados por uma
letra “d“. A seguir apresentamos alguns exemplos de números tipo dou-
ble:
10d
10.2d
1239831398.123213D

92 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 93


Conceitos Básicos da Linguagem Caracteres

Binário Octal Hexadecimal Decimal 10d2 que equivale a 1000.0


0 0 0 0 0.2d2 que equivale a 0.4
1 1 1 1
10 2 2 2
11 3 3 3 4.9 Caracteres
100 4 4 4 Caracteres são representados em Smalltalk precedidos do sím-
101 5 5 5 bolo ‘$’. Eles são instancias da classe Character e como todo tipo de
110 6 6 6 objeto literal necessitam apenas ser escritos para estarem declarados. A
111 7 7 7 seguir apresentamos alguns exemplos de objetos caracter:
1000 10 8 8 $% $4$$$a$ que equivale a um espaço
1001 11 9 9
1010 12 A 10
4.10 Strings
1011 13 B 11
1100 14 C 12 Strings também são objetos literais e são declarados como uma
1101 15 D 13 sequência de caracteres delimitados pos aspas simples. A seguir apre-
sentamos alguns exemplos de strings válidas:
1110 16 E 14
1111 17 F 15 ‘’
Tabela 4.3 Correlação entre várias bases numéricas ‘isto é uma string’
‘123#$%âbc’
Exponen- Números Inteiros e em ponto flutuante ainda podem ser escritos
ciação em forma de potência. Neste caso, utilizamos a seguinte notação: ‘copo d’’agua’

<número>e<potencia>
A seguir apresentamos alguns exemplos de números em forma Como podemos notar no último exemplo a aspa é representada
de potência, que também são conhecidos como números em notação duplicanda.
científica:
10e2
4.11 Booleanos
1232312.3232e132312
Existe, como já era de se imaginar apenas dois objetos boolea-
No caso de números do tipo double não podemos utilizar a letra
nos. um que representa o valor verdadeiro que no caso é true e o que
“e“ para inidicar que o número está elevado a um expoente. Em vez
representa o valor falso, denominado false. Eles são Instancias das clas-
disso, digitamos o expoente logo após a letra “d“. A seguir apresentamos
ses True e False respectivamente. Um erro muito comum quando esta-
alguns exemplos:

94 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 95


Conceitos Básicos da Linguagem Arrays

mos programando é digitar True ao invés de true. Isso significa que a Símbolo Comentário
classe está sendo referenciada ao invés do objeto.
#abcde começa com letra, então só aceita mais
Objetos booleanos são muito importantes e extensivamente utili- letras ou dígitos e _
zados em expressões lógicas e também são neles que alguns laços de #== começa com símbolo então só aceita mais
repetição e seleções condicionais são implementados. símbolos.
#’simbolo’ as áspas são desconsideradas em opera-
#’pneu radial’ ções com símbolos, porém se queremos
4.12 O Objeto Indefinido nil definir um símbolo com espaços, devemos
usá-las ao definí-lo.
O objeto nil é instancia única da classe UndefinedObject.
Tabela 4.4 Exemplos de simbolos válidos
nil é um conceito que Smalltalk herdou de LISP e vem do termo latim
nihil que significa “nada”. Quando criamos uma nova variável, ela por
Símbolo Comentário
definição armazena o valor nil, que significa que não referencia
nenhum objeto. Uma comparação possível, mas que não captura todo o #123adsas não pode começar com digitos
espectro do significado de nil é dizermos que nil corresponde ao #==10d não pode começar com caracter especial e ser
ponteiro nulo null em C++. seguido por digitos ou letras
Podemos explicitamente atribuir o valor nil a uma variável ##=== não se pode passar de dois caracteres especiais
caso desejemos que o objeto referenciado por aquela variável seja cole- Tabela 4.5 Exemplos de simbolos inválidos
tado pelo coletor de lixo. Note que isso só ocorrerá se nenhuma outra
variável referenciar também o objeto em questão.
4.14 Arrays
Arrays são literais que representam um coleção de objetos que
4.13 Símbolos podem ser acessados de maneira indexada. Qualquer outro objeto literal
Instâncias da classe Symbol são como strings porém possuem pode fazer parte de um array até mesmo outros arrays. A forma geral é
algumas propriedades adicionais. Eles não precisam estar delimitados apresentada a seguir:
por aspas como no caso de strings normais. Caso as aspas existam, elas #(<objetos literais separados por espaço>)
serão iguinoradas. O que caracteriza um símbolo é que ele sempre é
A seguir apresentamos alguns exemplos de arrays:
precedido por um símbolo #.
#($a $b $c $d $e $f)
Eles podem começar com letras ou caracteres especiais mas
nunca com números. Caso o símbolo começe com caracteres especiais #(1 2 3 4 5 6 7 8 9 0)
nenhuma letra ou dígito serão válidos, e caso ele comece com letras, #(1 2 3 $a ‘texto’ 12d2 1.1)
caracteres especiais não serão válidos. Abaixo apresentamos alguns
Existe um outro tipo de array suportado sob a forma de literal.
exemplos de símbolos válidos e outros inválidos:
Estamos falando de instancias da classe ByteArray. Objetos instancia-

96 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 97


Conceitos Básicos da Linguagem Outros Objetos Relevantes

dos a partir desta classe devem possuir apenas números inteiros vari- Esta é uma classe chave do Smalltalk e deve ser exaustiva-
ando de 0 a 255 como elementos e devem seguir a seguinte forma mente análizada durante o processo de aprendizado da linguagem. Mui-
padrão: tas das características desta tão importante classe serão abordadas no
#[<inteiros de 0 a 255 separados por espaço>] restante do livro.
A seguir apresentamos alguns exemplos de criação:
Pontos são utilizados exaustivamente pelo Smalltalk principal- Pontos
#[1 2 2] mente no que se refere a parte gráfica seja na criação de objetos gráficos
#[ 0 0 0 0 0 0 0 ou nos mais diversos pontos da linguagem. Podemos criar pontos de
0 0 1 1 0 0 0 diverças formas, mas a mais comum é enviando a mensagem binária
‘@<numero>’ à outro número.
0 0 1 1 0 0 0
0 1 1 1 1 0 0 ]
Instancias desta classes são muito úteis por exemplo para
manipulacão de imagens em tons de cinza utilizadas em informática
médica.

4.15 Outros Objetos Relevantes


Como já citamos a biblioteca de classes é bem vasta. Dessta
forma os próximos capítulos apresentarão vários conceitos de Smalltalk
e para tal sitaremos ainda várias outras classes. Porém existem algumas
classes que são tão básicas e tão utilizadas que vale a pela cita-las aqui
logo no começo do livro. Começaremos apresentando uma breve expli-
cação sobre a classe Object que é a classe mais fundamental em toda a
biblioteca de classes e que todas as outras classes são direta ou indireta-
mente filhas. Em seguida apresentaremos a classe Point e por fim apre-
sentaremos a classe Relation.
Figura 4.5 Implementação da mensagem ‘@’ da classe Point

Object A classe Object é superclasse de todos os objetos em Smalltalk. Na figura 4.5 vemos a implementação da mensagem ‘@’ na
Ela define o comportamento básico e também muitos dos mecanismos classe número. Ela cria uma instancia da classe Point a sendo o valor do
importantes da linguagem. Nela encontramos a implementação do meca- número que recebe a mensagem correspondente a coordenada x do
nismo de dependência que será visto em detalhes mais a frente no livro, ponto e o argumento da mensagem ‘@’ a coordenada y.
também encontramos os métodos responsáveis pela cópia de objetos e
o mecanismo de impressão.

98 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 99


Conceitos Básicos da Linguagem

0HQVDJHQVH
Um ponto pode ser criado a partir de qualquer número perten-
cente a hierarquia da classe Number. Desta forma, todos os pontos Capítulo 5
apresentados abaixo são válidos:
10@13
12.2@1.1
0pWRGRV
12.5@2
(10/3)@2
Podemos notar nos exemplos acima que um ponto não precisa
necessáriamente ter suas duas coordenadas como números do mesmo
tipo, embora coordenadas de diferentes tipos de números sejam rara-
mente utilizadas.

4.16 Exercícios
Neste capítulo você vai aprender como funciona a estrutura
1. Procure onde é implementada a mensagem ‘flush’ na classe Ran- básica que determina o funcionamento de um objeto em Smalltalk: o
dom. método. Além disso, neste capítulo será visto como métodos são invoca-
2. Expanda a hierarquia de classes de AritimeticValue e procure todas dos através do envio de mensagens a objetos, sendo descrito o meca-
as implementações da mensagem ‘+’. nismo básico de comunicação entre objetos, o envio e rebebimento de
3. Procure a implementação das classes que representam os objetos lit- mensagens. Várias peculiaridades desta importante parte do Smalltalk
erais e navegue pelos seus métodos. serão aqui abordadas. As três formas básicas que um método/menságem
4. Identifique qual o tipo dos seguintes objetos: pode assumir (unária, binária ou por palavra chave) serão discutidas em
a) 12 g) -1246733221 detalhes bem como o mecanismo de encadeamento de mensagens e de
precedência entre as mesmas. Por fim vamos discutir bom estilo de pro-
b) -12 h) $a
gramação de métodos.
c) #abc i) $$
d) #= j) $ Primeiramente apresentaremos uma definição sólida do que vem Estrutura do
a ser uma mensagem e um método. O mecanismo de execução de uma capítulo
e) ‘Smalltalk’ k) ‘a’
mensagem é aqui explicado em detalhes visando uma maior compreenção
f) 1246733221 l) ‘=’ global do smalltalk pelo leitor. Em seguida apresentaremos uma série de
5. Discutimos muito sobre arrays neste capítulo, mas nada falamos convenções muito úteis para definir o tamanho ótimo que um método deve
sobre matrizes. Sugira uma forma de como poderíamos implementar assumir, como definir bons nomes para métodos e argumentos e também
matrizes apenas utilizando arrays. como organizar seus métodos em protocolos utiizando para isso exemplos

100 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Mensagens e Métodos Mensagens Unárias

de soluções adotadas na própria hierarquia de classes do VisualWorks, e No restante deste livro utilizaremos os termos mensagem e
visando uma maior reutiização do código criado, aumento de método como sinônimos, mas o leitor deve ter em mente a diferença
manutenibilidade e legibilidade. A descrição do comportamento básico existente entre ambos.
que um método deve assumir será abordada a seguir, bem como os valo-
res de retorno que eles devem assumir.
Por fim diferenciaremos os método entre métodos de classe e 5.2 Mensagens Unárias
métodos de instância apresentando a teoria por traz de cada um deles,
Mensagens unárias são o tipo mais simples de mensagens.
as maneiras de manipula-los, vantágens e desvantágens e sutuações
Caracterizam-se por não possuírem nenhum argumento. Em geral dão
em que cada um se aplica.
idéia de uma ordem à um objeto.
Sintaxe:
5.1 Métodos X Mensagens <umObjeto> <umaMensagem>
Métodos e mensagens, em conjunto com os atributos, são par- onde <umObjeto> pode ser qualquer objeto instanciado e
tes fundamentais da orientação a objetos e tornam possível a estrutura também é conhecido como receiver e <umaMensagem> é qualquer
interna de um objeto. Porém uma pergunta pode estar incomodando o identificador válido de acordo com as regras vistas no capítulo 4. O
leitor. Qual a diferença entre um método e uma mensagem? exemplo 5.3 na página 103 apresenta algumas mensagens unárias.
A resposta é que objetos se comunicam através do invio e rece-
10 negated
bimento de mensagem e ações são executadas através de métodos.
256 fatorial
Para fazermo-nos mais claros, as menságens são o protocolo estabele- ScheduledWindow new
cido pelo qual os objetos se comunicam e os métodos são a implementa- OrderedCollection allInstances
ção destas mensagens. Desta forma quando executamos o exemplo 5.2,
Exemplo 5.3 Exemplo de mensagens unárias
o que ocorre é que a menságem rounded é enviada ao objeto tipo
Float 123.4 e em resposta ao recebimento desta menságem o método
‘rounded’ é executado. Como o leitor pode ver mensagens e métodos
tem sua grafia exatamente igual e para os programadores durante o pro-
5.3 Mensagens Binárias
cesso de criação de classes, a única preocupação está em definir os Mensagens binárias recebem este nome pois existem exata-
métodos, as existência das menságens são uma consequência direta da mente dois objetos envolvidos. Elas encontram um uso extensivo nas
criação de métodos. expressões aritméticas, aliás a maioria dos exemplos envolvendo este
tipo de mensagem são encontrados dentro das expressões aritméticas.
123.4 rounded Mas elas não são apenas usadas dentro deste contexto, são por exem-
Exemplo 5.2 Envio da mensagem “rounded” ao número ponto flutuante 123,4 plo usadas para a concatenação de strings e para a criação de relaciona-
mentos.

102 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 103


Mensagens e Métodos Mensagens Binárias

O Smalltalk é muito flexível com relação aos seus tipos de cons- + uma mensagem para executar a soma de dois objetos
trução. Desta forma é permidito a criação de menságens binárias da - esta para executar a subtração
maneira que o leitor bem quizer. -> usado em relacionamentos
Uma mensagem binária tem como forma básica: , usada para concatenação de strings
@ cria uma instancia da classe Point
<umObjeto> <umaMensagem> <outroObjeto> Exemplo 5.4 Símbolos comumente utilizados para compor mensagens binárias
<umObjeto> pode ser qualquer objeto instanciado e também
é conhecido como receiver, <umaMensagem> deve ser um símbolo
especial ou combinação deles respeitando as regras apresentadas na
tabela 5.1 na página 104.
Um dado interessante é que internamente o Smalltalk utiliza
símbolos para representar os nomes de métodos. Como menságens
binárias devem necessáriamente utilizar os simbolos especiais (caracte-
res de comparação e pontuação) a parte das regras para criação de sím-
bolos referente a utilização de caracteres especiais deve ser respeitada.

regra descrição
iniciar com caracter espe- qualquer mensagem binária deve iniciar com um dos
cial seguintes caracteres (! @ # $ < > = + - / * \ & ~ ,)
possuir apenas dois carac- uma mensagem binária deve ter no máximo dois caracte-
teres especiais res especiais
não possuir outros tipos de apenas são permitidos caracteres especiais na criação de
caracteres menságens binárias
Tabela 5.1 Regras para formação de mensagens
Por fim <outroObjeto> é o argumento passado ao receiver Figura 5.1 Implementação da mensagem binária +
pela mensagem. Ele, pode a priori ser qualquer objeto.
Dentre as classes da biblioteca de classes, encontramos várias
Em muitas linguagens estes símbolos são operadores aritméti-
mensagens binárias básicas que tem o seu uso consagrado. A tabela 5.2
cos com precedência de execução e função bem definida. No Smalltalk
na página 106 traz um resumo explicando os principais. O exemplo 5.5
não existe esta idéia de operadores aritméticos, tudo no mundo Smalltalk
na página 106 mostra como podemos utilizar mensagens binárias.
são objetos que se comunicam através de mensagens. Logo um número
também é um objeto que para se somar com outro numero deve mandar Para entender como as mensagens binárias funcionam, nada
uma mensagem para ele. A figura 5.1 mostra a implementação da opera- melhor que um exemplo. Como as expressões aritméticas são o exemplo
ção soma como um método associado a uma mensagem binária. mais comum de mensagens binárias, e serão extensivamente utilizadas

104 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 105


Mensagens e Métodos Inexistência de precedência entre Operadores

+ Mensagem para perfazer a soma entre de objetos ção infixada. Tomemos a expressão 10 + 2. O que temos aqui são dois
objetos, instâncias da classe Integer (10 e 2), e uma mensagem entre
- Mensagem para perfazer a subtração entre de objetos eles. Como devemos interpretar esta expressão ? O que ocorre na reali-
* Mensagem para perfazer a multiplicação entre dois objetos dade é que o objeto mais a esquerda (no caso o 10) recebe uma mensa-
/ Perfaz a divisão, e cria uma instância da classe Fraction, quando aplicado a gem ‘+’ para somar o seu valor com o valor do objeto que está sendo
dois inteiros passado por argumento (no caso o 2).

** Executa uma exponenciação


// Usada para operação de módulo, retorna o resto da divisão 5.4 Inexistência de precedência entre Operadores
\\ Usada para divisão inteira, retorna a parte inteira da divisão
Não existe ordem de precedência entre os “operadores” em
~= Operador para a comparação em desigualdade Smalltalk. Pense. Se todos os números são objetos e os “operadores”
~~ Verifica se os dois objetos envolvidos são o mesmo objeto, retorna um objeto nada mais são que mensagens, como poderia existir ordem de prece-
True ou False dência ? Quando um programador desavizado cria uma expressão arit-
== Verifica se ob objetos envolvidos são o mesmo objeto mética em Smalltalk e confia que a multiplicação será executada antes
da adição ele está incorrendo num dos erros mais básicos do Smalltalk.
& Perfaz a operação de E lógico, retorna um objeto True ou False
Para tornar o conceito mais claro, uma soma subtração, radicia-
| Perfaz a operação de OU lógico, retorna um objeto True ou False
ção ou exponenciação tem exatamente o mesmo valor para o Smalltalk.
, Concatena duas strings Veja no exemplo 5.6 a ordem de execução das mensagens.
@ Cria uma instancia da classe Point
1. 10 + 2 * 4
-> Usado para a criação de relacionamentos
2. 2 * 4 + 10
Tabela 5.2 Mensagens binárias mais comuns
Exemplo 5.6 Ordem de execução das mensagens

10 + 10 Estas duas expressões teriam um resultado diferente se fossem


20 ** 2 avaliadas utilizando o Smalltalk. A primeira valeria 48 e a Segunda 18.
‘Small’ , ‘talk’ Vamos passo a passo.
10 -> ‘dez’
Exemplo 5.5 Mensagens binárias

durante o desenvolvimento de aplicações optamos por escolhe-las como


exemplo.
Você está acostumado com a notação infixada1 utilizada para 1. Em contraste com a notação pré-fixada, que vê todo operador aritmético como uma
operações matemáticas desde a antigüidade. A utilização das operações função, onde 2 + 3 é representado + 2 3 ou + ( 2, 3) e a notação pós-fixada, utilizada
matemáticas como mensagens permite que continuemos a usar a nota- pelas calculadoras Hewlett-Packard, onde o operador é colocado depois dos operan-
dos: 2 3 + [enter].

106 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 107


Mensagens e Métodos Mensagens por Palavra Chave (keyword messages)

Uma Na primeira seqüência de operações do exemplo 5.5, a primeira a próxima mensagem da linha de comando será enviada a este objeto
mensagem é parte avaliada seria 10 + 2 e depois se avaliaria 12 * 4 resultando em 48, resultante.
enviada ao já no segundo exemplo primeiro se avaliaria 2 * 4 e depois se avaliaria 8 Se você já tem experiência de programação mas nunca progra-
resultado da + 10 resultando em 18. Logo descobrimos uma das primeiras regras do mou em Smalltalk nem em LISP antes, isto é bem diferente do que você
mensagem mecanismo de mensagem. Todas as mensagens são avaliadas da estava acostumado e necessita de um tempo para se acostumar. Mas
anterior esquerda para a direita. A frente veremos as outras regras. Esta regra é você vai ver que é muita mais intuitivo do que a forma tradicional à qual
muita fácil de se compreender se mantivermos em mente que o que você estava acostumado e que assim você programa de forma muito
acontece neste exemplo não é uma seqüência de operações em uma mais natural, muito mais próxima de sua forma de pensar. Mais sobre
linha de comando, mas sim uma seqüência de mensagens, cada qual esse tema você vai ver na seção sobre encadeamento de mensagens,
enviada ao objeto resultante da operação anterior. Lembre-se que fala- mais adiante neste capítulo.
mos que Smalltalk herdou de LISP a característica de que todo método
retorna um valor. Isto significa que o envio de uma mensagem a um
objeto, que acarreta a execução do método com aquele nome, devolverá
sempre o que foi definido pelo programador como sendo o valor de
5.5 Mensagens por Palavra Chave
retorno do método. Isto significa que, ao enviarmos uma mensagem a (keyword messages)
um objeto, teremos sempre um objeto como resposta. No caso aritmé- Até agora vimos mensagens sem argumentos (mensagens uná-
tico, quando definimos um método que implementa uma operação arit- rias) e mensagens com exatamente um argumento (mensagens biná-
mética, implementamo-lo de tal forma que devolve o resultado dessa rias). Então é de se esperar que mensagens por palavra chave sejam
operação. mensagens com possivelmente, mais de um argumento ? Sim. Mensa-
Observando essa filosofia, podemos ler o código do primeiro gens por palavra chave são mensagens que relacionam um identificador
exemplo 5.6 da seguinte forma: a cada argumento que se deseja passar para um objeto.
• enviar a mensagem + com 2 como argumento ao objeto inteiro Este tipo de mensagem é diferente das funções que encontra-
10 devolve como resultado o objeto 12; mos em C por exemplo. Em C, o método possui um nome e para cada
• é este objeto 12 que recebe a próxima mensagem, * , que é argumento existe um tipo e caso desejemos um nome para este argu-
enviada com 4 como argumento; mento. Em Smalltalk o nome do método é suprimido e as menságens por
• enviar * com 4 como argumento ao inteiro 12 resulta no objeto palavra chave são costruidas como segue.
48, que é o resultado final desta “linha de comando”.
A sintaxe básica de uma mensagem por palavra chave é a
A outra linha do exemplo 5.6 e todos os encadeamentos de seguinte:
mensagens binárias em Smalltalk funcionam da mesma forma. Na ver- <objeto> <ident1>: <arg1> <ident2>: <arg2> .....
dade, você pode usar isto como uma filosofia geral ao programar: o <identn>: <argn>
resultado do envio de qualquer emnsagem a um objeto é outro objeto2 e
Como podemos observar não existe um nome para a mensá-
gem, ela é diferenciada das outras pelo conjunto de palavras chave que
as compoe.
2. Ou o mesmo objeto, se o método em questão termina com ^self. Veremos isto adiante.

108 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 109


Mensagens e Métodos Encadeamento de Mensagens

O limite de palavras chave que uma mensagem pode ter é 255, truídas. O exemplo 5.8 abaixo será usado para o entendimento do
porém não é aconselhável que se escreva métodos com tantos argumen- funcionamento do encadeamento de mensagens.
tos. Se um método desta magnitude é necessário, certamente ele pode
ser decomposto em outros tantos métodos. Esta é a prática corrente em 10 ** 2 + 1
programação orientada a objetos. No exemplo 5.7 podemos ver algumas Exemplo 5.8 Duas mensagens encadeadas
mensagens por palavra chave.
Vamos entender como a expressão acima é executada pelo
"aqui vemos que a mensagem só tem um argumento 10 mas a mensagem se Smalltalk:
caracteriza como keyword message pela existência do símbolo : a Quando o número 10 (instância da classe SmallInteger) recebe
frente da mensagem." a mensagem binária ‘**’ e o argumento 2, ele retorna o número 100,
(também uma instância da classe SmallInteger). O número 100 rebebe
index max: 10
a mensagem ‘+’ e o argumento 1, retornando finalmente o número 101.
"exemplo com dois argumentos" Fazemos questão de usar exemplos numéricos aqui para, por um lado
#(1 2 3 4 ’abc’ ’def’) copyFrom: 1 to: 3 conscientizar o leitor de que não existem tipos primitivos ou coisas simi-
lares em Smalltalk, mas sim que tudo é objeto, e mesmo números intei-
"exemplo de inclusão de um item em um dicionário" ros vão se comportar como objetos com métodos e respostas a
aDict at: ’abc’ put: 3 mensagens. Por outro lado queremos deixar claro que conceitos de lin-
Exemplo 5.7 Mensagens por palavra chave guagens estruturadas como precedência de operadores em Smalltalk
perdem o sentido, já que em Smalltalk todas as operações são mensa-
gens, não havendo operadores de nenhum tipo.
5.6 Encadeamento de Mensagens Agora veremos como uma mesma expressão pode fazer uso do
encadeamento de mensagens para torná-la mais simples. Temos uma
Já vimos que qualquer mensagem enviada para um objeto acar-
String ‘ST80’ composta por caracteres alfanuméricos e queremos extrair
retará no retorno de outro objeto. Isso permite o encadeamento de várias
a sub-string ‘80’ e transformá-la em um número negado. Tal intento pode-
mensagens em uma única expressão. Essa é uma das características
ria ser obtido como apresentado no exemplo 5.9 na página 111.
mais importantes do Smalltalk, faz-se necessário que o leitor tenha-a
sempre em mente. Ela foi herdada do LISP e fornece ao Smalltalk ótimas
|subString num|
características para sua aplicação em IA e processamento simbólico.
As expressões aritméticas fazem um uso extensivo do meca- subString := ’ST80’ copyFrom: 3 to: 4.
nismo de encadeamento de mensagens. Uma operação entre números num := subString asNumber.
sempre retornará um número, mesmo que ele mude de tipo, como por num := num negated.
exemplo uma divisão de dois inteiros poderá acarretar no retorno de um Exemplo 5.9 Exemplo sem a utilização do encadeamento de mensagens
número real, ma ele não deixará de ser número. Baseando-se nesta pro-
priedade dos números é que as expressões aritméticas podem ser cons-

110 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 111


Mensagens e Métodos Encadeamento de Mensagens

A mesma tarefa, poderia fazer uso do mecanismo de encadea- ser que você não perceba de imediato, mas na segunda versão do
mento de mensagens e simplificar de maneira significativa o processo. código, tanto add: 1 como add: 2 são enviadas à mesma citação de
Esta nova versão pode ser observada no exemplo 5.10. ord no código. Na primeira versão do código, nós citamos ord duas
vezes, uma para receber a mensagem add: 1 e outra para receber a
|num| mensgaem add: 2.
Agora o que ocorreria se ao invés de criarmos a coleção antes
num := (’ST80’ copyFrom: 3 to: 4) asNumber negated.
de enviarmos a sequência de mensagens encadeada com a utilização de
Exemplo 5.10 Exemplo utiilzando o encadeamento de mensagens “ ; “ o que ocorreria ? O exemplo 5.12 ilustra esta situação:

Ordem de Algumas considerações devem ser feitas. A ordem em que as


"exemplo de cascateamento de mensagens em uma única linha"
avaliação e mensagens serão avaliadas nem sempre seguem a regra da esquerda |ord|
cascatea- para a direita. No próximo tópico veremos as 5 regras básicas para avali-
mento de ação de expressões. ord := OrderedCollection new add: 1; add: 2.
mensagens
Existe uma maneira de enviarmos várias menságens a um Exemplo 5.12 Exemplo de cascateamento de menságens em uma única linha
mesmo objeto, sem necessáriamente referenciarmos explicitamente o
objeto a cada nova menságem. Para fazer isso utilizamos o operador “;“. Se verificarmos o valor de ord através de uma inspeção vere-
Chamamos a isto de Cascateamento de Mensagens. O exemplo 5.11 na mos que ele conterá o número 2 e não a coleção. Porque isso ocorre ?
página 112 apresenta dois trechos de programa, um sem e outro com a
utilização do “;“ para a realização do cascateamento de várias mensa- Se pensarmos no mecanismo de cascateamento de menságens Usando
gens seguidas ao mesmo objeto. Como o código está indentado, pode podemos ver passo a passo como a expressão é executada: Em primeiro yourself
lugar a classe OrderedCollection recebe a menságem ‘new’ criando
"exemplo sem a utilização de ;" assim uma instancia desta classe. em seguir a menságem ‘add:’ com o
|ord| argumento 1 é enviada a instancia de OrderedCollection. O objeto 1 é
ord := OrderedCollection new. adicionado à coleção e o inteiro 1 é ser retornado. Mas como o símbolo “
ord add: 1. ; “ é encontrado a outra menságem ‘add:’ com o argumento 2 é enviada a
ord add: 2. instancia de OrderedCollection. O objeto 2 é adicionado a coleção e
retornado. Assim a variável ord conterá o objeto 2 e não a coleção.
"exemplo cascateado com a utilização de ; " Porém existe uma forma de atribuir a coleção previamente criada a variá-
|ord| vel. Para tal utilizamos o método ‘yourself’ que é implementado na classe
ord := OrderedCollection new. Object. Este é um método especial que fornará o retorno do objeto que
ord add: 1; resebeu as menságens em cascata. O exemplo 5.13 apresenta a utiliza-
add: 2.
ção da mensagem ‘yourself ’ para a correção deste problema.
Exemplo 5.11 Cascateamento de mensagens utilizando “ ; “

112 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 113


Mensagens e Métodos Como a mensagem é executada?

"exemplo de cascateamento de mensagens usando yourself" 1. Como os parênteses alteram a ordem de execução a mensagem
|ord| ‘copyFrom:3 to: 4’ enviada para a string ‘ST80’ será executada
primeiro. Retornando a substring ‘80’.
ord := OrderedCollection new add: 1; add: 2; yourself. 2. A próxima mensagem a ser executada é a mensagem ‘asNumber’
Exemplo 5.13 Utilização da menságem ‘yourself’ (isso porque ‘asNumber’ e ‘negated’ são ambas menságem unárias)
obedecendo a regra 1 que dita que a execução é efetuada da
esquerda para a direita.
3. Finalmente a mensagem ‘negated’ é executada retornando um
5.7 Precedência de Mensagens SmallInteger valendo –80.
Como vimos até agora, no Smalltalk não existe o conceito de
precedência de operadores haja visto que nem existem operadores. Ao
invés de precedência de operadores encontramos um mecanismo de 5.8 Como a mensagem é executada?
precedência de mensagens. O mecanismo se baseia em 5 regras bem
Quando um objeto recebe uma mensagem, o Smalltalk verifica
simples que devem estar bem aprendidas entre seus conhecimentos
no dicionário de métodos da classe que define o objeto. Se um método
básicos de Smalltalk, afim de evitar maiores complicações posteriores.
com o mesmo nome da mensagem é encontrado no dicionário, o método
Elas podem ser vistas na tabela 5.3.
correspondente a mensagem é executado. Caso o um método de
mesmo nome não seja encontrado, o Smalltalk procura nas superclasses
regra descrição
da classe original, começando na classe logo acima e indo até encontrar
número 1 A avaliação de uma expressão é feita da esquerda para um método de mesmo nome que a mensagem. Se tal método não for
a direita encontrado, uma janela de exceção é aberta com a mensagem de que
número 2 As mensagens unárias tem a maior precedência aquele objeto não entende a mensagem enviada.
número 3 As mensagens binárias vem logo após as unárias em No exemplo 5.14 tentamos enviar para um objeto String uma
precedência mensagem que este objeto não "entende". O fato de o envio desta men-
número 4 Por último temos as mensagem por palavra-chave sagem resultar num erro, significa que nem este objeto nem um de seus
número 5 O uso de parênteses muda a precedência das mensa- pais na hierarquia de classe até Object implementa um método com o
gens e sempre será a precedência mais alta de todas, nome rounded.
sendo executado primeiramente os parênteses mais
internos. ‘Smalltalk’ rounded
Tabela 5.3 Regras de precedência de menságens Exemplo 5.14 Mensagem enviada para um objeto que não a implementa
Agora que já conhecemos as regras de precedência, reportemo-
nos novamente ao exemplo 5.9 na página 111. Os parênteses contidos A mensagem de erro gerada é mostrada na figura 5.2 na página
na expressão poderiam causar dúvidas até então. Analisando a expres- 116.
são seguindo as regras de precedência o entendimento as mesmas se
fará mais claro.

114 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 115


Mensagens e Métodos Nomes para Métodos

5.10 Nomes para Métodos


O nome dado a um método é de suma importância dentro da
metodologia orientada a objetos. Um nome auto-elucidativo ajuda muito
no entendimento da sua função. Na biblioteca de classes do Smalltalk
encontramos nomes de métodos bem grandes como:

FindPreviousString: aString startingAt: start


IndexOfSubCollection: substring startingAt: start
Exemplo 5.15 Exemplos de nomes para métodos

O programador deve assumir um compromisso de bom senso


com seus métodos. Imagine se um dado método se chamasse:
adicionaItensAListaDeFuncionarios
Certamente esta não é uma das melhores práticas em progra-
Figura 5.2 Exceção criada pelo envio de uma mensagem inválida mação. Tal método muitas vezes poderia ser ter seu nome abreviado
porém sem comprometer a sua clareza. Por exemplo a palavra Adiciona
poderia ser trocada para add sem comprometimento do entendimento.
5.9 Métodos (A definição de uma mensagem) Se o método assume um nome muitíssimo longo para elucidar
Métodos, como vimos no início deste capítulo, são a implemen- todo o seu funcionamento, isso pode evidenciar que ele deve estar
tação de uma mensagem. Eles contém o código que será executado em sobrecarregado de funções. Uma boa política em criação de métodos é
resposta ao envio de uma mensagem. Quando uma mensagem é envi- faze-los o mais simples possível. Desmembrar um método sobrecarre-
ada a um objeto, o Smalltalk verifica o dicionário de métodos a procura gado de funções em vários métodos mais simples sempre lhe permite
de uma implementação para aquela mensagem, se o método não é uma maior reutilização do código criado.
encontrado na classe, o procura continua nas superclasses da classe em Assume-se uma convenção para a criação de métodos dentro
questão. Caso o método não seja encontrado em nenhuma das super- da biblioteca de classes. Todo método deve começar com letra minús-
classes então uma exceção é gerada. cula, e caso o nome do método seja composto por várias palavras, estas
O importante em se tratando de métodos, é primar por uma boa devem ter sua primeira letra em maiúsculo. Isso facilita devéras a legibili-
implementação, visando assim maior legibilidade e reutilização do dade de seus nomes. No exemplo 5.16, mais alguns nomes de métodos.
código. A seguir veremos convenções utilizadas na biblioteca de classes
do Smalltalk. SqrtRounded
IsNumber
SuspendUnconditionally
Exemplo 5.16 Outros exemplos de nomes para métodos

116 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 117


Mensagens e Métodos Métodos para Acesso a Atributos

Para métodos tipo keyword messages, onde cada argumento devem ter o mesmo nome que o atributo a que eles destinam viabilizar o
tem o sua respectiva palavra chave valem as mesmas regras. Muitas acesso externo.
vezes nos deparamos com métodos que tem um nome bem elucidativo Como em alguns casos existe a necessidade de se retornar o
porém as palavras chave são paupérrimas semanticamente, e vice- valor de um argumento e também de se alterar seu valor dois métodos
versa. serão necessários. Desta forma, métodos de acesso são, em geral, cria-
Os métodos que retornam booleanos devem ter a aparência de dos aos pares. O exemplo 4.17 apresenta a implementação dos métodos
uma pergunta, e os métodos de converção de objetos devem ser prece- de acesso para o atributo idade de uma classe ipotética.
didos de palavras que mostrem que eles farão uma converção. Os
demais métodos deverão estar todos no modo imperativo. "método para acesso do atributo idade"
idade
"métodos que retornam booleanos" ^idade
isNil
hasData "////////////////////////////////////////"
ehInteiro
estaVazio "método de acesso para alteração do atributo idade"
idade: umaIdade
"métodos de conversão" idade := umaIdade.
asFloat Exemplo 5.18 Métodos de acesso a atributos
asOrderedCollection
comoInteiro No primeiro método vemos que a primeira ocorrência da palavra
Exemplo 5.17 Exemplos de métodos para conversão e que retornam booleanos idade é o nome do método unário e a segunda precedidada do caracter
de retorno “^“ faz referência a variável de instancia.
No segundo exemplo a primeira ocorrencia da palavra idade faz
5.11 Métodos para Acesso a Atributos parte do nome do método por palavra chave ‘idade:’ e a segunda ocor-
rência à variável de instanicia. A primeira vista pode parecer um pouco
Como vimos no capítulo anterior, um objeto é composto por atri-
confuso, mas a medida que o leitor for se acostumando com a biblioteca
butos e mensagens. Em Smalltalk todos os atributos são invariavelmente
de classes e com o Smalltalk verá que esta forma de construção de
privados, ou seja, não podem ser acessados fora do objeto, e todos os
métodos de acesso é muito prática e extensivamente utilizada.
métodos são públicos, ou seja, completamente visíveis de fora do objeto.
Desta forma, para se acessar atributos fora do escopo de um Basicamente, dividimos um método em identificador/palavras Qual o
objeto uma prática muito comumente adotada é se criar métodos de chave e código. A convenção adotada na biblioteca de classes é de que tamanho de
acesso a atributos. o tamanho do código deve girar em torno de sete linhas. Criando méto- um método?
Um dado interessante é que embora o Smalltalk não permite que dos com número reduzido de linhas o programador facilita a legibilidade
um objeto implemente dois métodos que tenham o mesmo nome, um e entendimento do código, além de tornar seu código mais reutilizável.
método e um atributo podem ter. Desta forma, métodos de acesso

118 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 119


Mensagens e Métodos Indentação para métodos

Para o identificador a convenção foi descrita no tópico anterior. Neste exemplo o “estado” do objeto ordCol é alterado pois passa
Quanto ao número de argumentos, é costume que eles não devem ocu- do estado vazio para o estado contendo um objeto do tipo SmallInteger.
par mais que uma linha de código, ou seja, todos os argumentos do Métodos que devem ser evitados a qualquer custo, são aqueles
método devem caber na mesma linha do identificador. Embora o Small- que desempenham as duas funções, ou seja, que retornam algum objeto
talk aceite métodos com até 255 argumentos, a criação de métodos com significativo (entenda-se um objeto diferente de self) e que alteram o
muitos argumento cai novamente na pergunta? Será que este método estado do objeto que recebe a mensagem. Pode ser que em alguns
não poderia ser subdividido? As vantagens deste procedimento já estão casos isso seja extremamente necessário, mas tenha em mente que
mais que fomentadas neste ponto do livro. essa é uma prática pouco recomendada.

5.12 Tipos de métodos 5.13 Indentação para métodos


Os métodos podem ser subdivididos em dois grandes grupos, A indentação é outro fator que colabora para a legibilidade e
conforme o papel que desempenham. entendimento de um método. Um método bem indentado parece aos
O primeiro grupo é composto por métodos que retornam algum olhos do programador e de qualquer outra pessoa que venha a inspecio-
objeto que não seja self . Este tipo de método, em alguns casos, apenas nar o código muito mais bem escrito. Passa uma idéia de ser um método
retorna o conteúdo de um atributo, ou em outros causa um processa- consistente e que cumpre a função a que se destina sem maiores per-
mento e retorna o resultado, sem no entanto, alterar o estado do objeto meios.
que recebeu a mensagem, ou seja sem alterar atributos O método mostrado na figura 5.3 na página 122 foi extraído da
A mensagem negated serve como exemplo para este grupo classe Integer. Observe que sempre que um laço de repetição é aberto,
de métodos. Ela retorna um número igual ao que recebeu a mensagem, o código interno fica deslocado quatro casas para a direita. Assume-se
porém sem alterar o valor do número original. que a condição de entrada no laço deve estar na linha superior ao laço
O outro grupo se compõe de métodos que causam alterações no propriamente dito. O mesmo é aplicado a decisões. Issa é a indentação
estado do objeto que recebe a mensagem, retornando apenas self (o utilizada pela biblioteca de classes mas sinta-se livre para adotar aquele
retorno de self se faz por definição, pois como já sabemos, tomo método que mais lhe aprouver.
retorna obrigatoriamente um objeto em Smalltalk). A adição de um novo Para os preguiçosos, o system browser do VisualWorks fornece
elemento a uma coleção serve como exemplo como podemos ver no uma funcionalidade que formata automaticamente seu método no padrão
exemplo 5.19. adotado pela biblioteca de classes. Para usar esta funcionalidade, acione
o menu com o botão direito do mouse e selecione a opção <Format>.
|ordCol| (Como os botões do mouse podem ser mudados ou o seu computador
ordCol := OrderedCollection new. pode não possuir um mouse de 3 botões, entenda-se por botão direito o
ordCol add: 1. <Operate> button, também conhecido como yellow button no Visu-
Exemplo 5.19 Método que altera o estado interno do objeto alWorks).

120 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 121


Mensagens e Métodos O que um método retorna ?

Figura 5.4 Exemplo de método nao decompilado

Figura 5.3 Indentação padrão utilizada na biblioteca de classes

5.14 O que um método retorna ?


O caracter “^” representa o símbolo de retorno em Smalltalk.
Quando ele é encontrado dentro de um método que está sendo execu-
tado , o método é automaticamente abandonado e o retorno é feito. Uti-
liza-se retornos dentro de condicionais ou laços de repetição para forçar
a saída.
Por definição, quando não se especifica qual o retorno do
método ele retorna self, embora este fato não apareça explicitamente no
código. Na figura 5.4 mostramos um método e seu respectivo decompi-
lado para elucidar melhor este conceito.
A figura 5.4 apresenta o código original extraído de uma classe
Figura 5.5 Exemplo de método decompilado
implementada por nós denominada Perceptron. Note que não existe
nenhum retorno neste método. Já a figura 5.5 na página 123 apresenta o

122 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 123


Mensagens e Métodos Alguns protocolos comumente utilizados

mesmo método, porém em sua versão decompilada. O ^self torna-se


então visível.
Para ver um método em sua forma decompilada basta segurar a
tecla shift e então clicar sobre o método.
Também é necessário salientar que um método retorna um e
somente um objeto, desta forma para retornarmos mais de um objeto de
um método devemos utilizar uma coleção qualquer para agrupa-los tor-
nando-os assim um único objeto.

5.15 Argumentos para métodos


Como sabemos, devido a linguagem Smalltalk não ser tipada,
qualquer objeto pode ser passado q método que esperam argumentos
(métodos binários e por palavra chave). Se um objeto diferente do que o
esperado por um método o é passado, podem vir a ocorrer erros, então
faz-se necessário que o leitor fique atento a este fato.
Outro ponto importante com relação a argumentos é que ao pas- Figura 5.6 Eexemplo de utilização da mensagem ‘copy’
sarmos um argumento a um método o que estamos fazendo na realidade
A mensagem copy existe para todas as classes da biblioteca
é apenas passando uma referência. Em casos onde o objeto passado
de classes pois é implementada na classe Object. Existem algumas vari-
como argumento a um método é armazenado (a título de exemplo pode-
antes da mensagem copy com outras características também implemen-
mos citar os métodos de acesso que alteram atributos), na verdade a
tadas na classe Object. Para ver estas outras menságens verifique o
referência ao objeto é armazenada, desta forma se alguma alteração for
protocolo “copying“ da classe Object.
feita dentro do método ao atributo, o objeto em si muda, ou seja, a altera-
ção é permanente para todos que visualizam ou tem acesso ao objeto.
Então podemos dizer que em Smalltalk só existe passagem pe parâme-
tros por valor? Errado. existe uma maneira de não passar uma referência 5.16 Alguns protocolos comumente utilizados
ao objeto como argumento mas sim uma cópia do mesmo. Para fazer Ou se observar o system browser do VisualWorks, notamos que
isso, devemos no momento em que referênciamos o objeto (durante o ele é dividido em 5 áreas. A terceira área da esquerda para a direita é
envio da mensagem), enviar a mensagem ‘copy’ ao argumento. Isso fará chamada de method protocol (como visto no capítulo 2). Este campo tem
que um cópia do objeto seja passada ao invés de uma referência ao efeito puramente organizacional em seu código, e é uma ótima ferra-
mesmo. A figura 5.6 mostra um exemplo de utilização da mensagem menta para manter seus métodos organizados.
copy.

124 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 125


Mensagens e Métodos Métodos de Classe e Métodos de Instância

Na biblioteca de classes alguns protocolos são comumente utili- como as comumente encontradas em funções de uma linguagem estru-
zados. Na tabela 5.4 listaremos alguns deles mas saiba, pode-se criar turada, logo, comentários dentro do código se farão raramente necessá-
qualquer protocolo de método que lhe pareça conveniente. rios.

protocolo descrição
initialize- métodos de inicialização e finalização de objetos. Utilizados para 5.18 Métodos de Classe e Métodos de Instância
release configurações iniciais e finais e definição de valores padrão.
Ainda podemos subdividir os métodos em outros dois grupos.
accessing métodos para acesso a atributos. • Métodos de Instância
private métodos que não se deseja que sejam utilizados fora do escopo da • Métodos de Classe
classe, embora o protocolo não exerça nenhum efeito proibitivo ao Todo o conteúdo discutido anteriormente se aplica tanto a méto-
acesso, apenas sugere que não sejam usados.
dos de instancia quanto a métodos de classe. A diferença reside no fato
adding métodos de coleções para adição de novos ítens de mensagens de instancia só poderem ser enviados para instancias de
deleting métodos de coleções para remoção de ítens uma determinada classe, e mensagens de classe só poderem ser envia-
dos para a classe que as implementa.
printing métodos para impressão de objetos e de seus conteúdos
Quando uma classe recebe uma mensagem ela procurará a
arithmetic métodos para perfazer operações aritiméticas
implementação da mensagens diretamente entre os métodos de classe.
enumerating métodos para iterações numéricas Já quando uma instancia da classe receber uma mensagem ela procu-
comparing métodos para comparação de valores e comparações entre objetos. rará o método correspondente a mensagem dentre os métodos de ins-
Tabela 5.4 Protocolos comumente utilizados pela biblioteca de classes tancia.
No system browser do VisualWorks, a implementação dos méto-
dos de classe e métodos de instancia fica armazenada em locais distin-
5.17 Comentários tos, bastando selecionar entre as opções instance e class para ver e
edita-los.
Os Comentários proporcionam maior legibilidade para o seu
código. Por definição na biblioteca de classes, os comentários sempre Mas o leitor pode estar se perguntando por que existem métodos
vem logo abaixo do nome do método. Não se deve economizar no tama- de classe? A resposta é simples. Eles são utilizados para retorno de
nho de comentários. Se a complexidade da mensagem for grande constantes, para perfazer operações que não compensariam a criação
comentários minuciosos devem ser providos. de todo um novo objeto, e também para as operações de instanciação de
objetos do tipo da classe que os implementa e ainda de outras classes.
Porém não devemos comentar tudo que aparece pela frente.
Existem métodos tão simples, como os métodos de acesso a atributos,
ou métodos que se responsabilizam por tarefas tão simples que o próprio
nome já pode ser considerado um comentário. Prime por métodos curtos.
5.19 Exercícios
Como eles não terão muitas linhas, não terão operações intermediárias 1. Diferencie menságem de método.

126 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 127


Mensagens e Métodos Exercícios

Em seguida utilize o workspace e inspecione as expressões para


conferir os resultados.
3. Como devemos proceder para passar uma referência a um objeto
como argumento a uma menságem e o que devemos fazer para pas-
sar uma cópia do mesmo objeto?
4. Se inspecionarmos a seguinte expressão o que ocorrerá?
OrderedCollection new add: 1; add:2; add:3.
Caso queiramos retornar a coleção criada o que poderíamos fazer?

Figura 5.7 Exemplo de um método de classe

2. Seguindo as regras de precedência entre menságens responda o


valor a ser retornado por cada uma das seguintes sequências de
menságens:
a) 12 + 10 + 1
b) 2 * 8 / 4
c) 2 * (8 / 4)
d) 4 + 4 * (12 - 3) / ((2 + 2) - 2 * 3)
e) ((2 * 2 + (2 + 2) / 3 + 2) * 4) + 1
f) (((2 * 2 + (2 + 2) / 3) + 2) * 4) + 1
g) (2 ** 2) / ( (14 / 3) negated ) rounded

128 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 129


Mensagens e Métodos

Capítulo 6 9DULiYHLV

Existem vários tipos de variáveis em Smalltalk. Neste capítulo


vemos as diferenças entre e características de cada tipo. Veremos como
funciona o conceito de inexistência de tipo (não-tipagem) de variáveis e
como você utiliza isto para flexibilizar ao máximo seus programas através
da utilização dos recursos de polimorfismo. Neste capítulo você verá tam-
bém como usar variáveis privadas e compartilhadas, de classe, estáticas e
temporárias. Por fim vamos falar de estilo de nomeção de variáveis em
Smalltalk.

6.1 Variáveis em Smalltalk


O esquema representado na figura 6.1 na página 132 apresenta
de uma maneira gráfica o esquema empregado para tipos e escopo de
variáveis no VisualWorks. Aparentemente o esquema é grande e sucinta-
nos a acreditar que o esquema de variáveis é complexo, mas com o decor-
rer deste capítulo veremos que variáveis no VisualWorks são bem simples
de serem entendidas e manipuladas.

130 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Variáveis Não-Tipagem

as variáveis normalmente e geralmente não pensa neste assunto. O


Variável único momento em que você deve ter em mente que toda variável é um
ponteiro, é quando você vai alterar o valor de algo passado como parâ-
metro em um método: todo parâmetro em Smalltalk é passado por
referência. Isto significa que se você alterar um objeto passado como
Compartilhada Privada parâmetro para um método, este objeto também vai ser alterado no
escopo externo ao método. Se você tem dúvidas sobre a diferença entre
pasagem de parâmetros por valor e passagem de parâmetros por refe-
rência, procure um bom livro de Estruturas de Dados ou de Programação
Estática Estática Temporária Classe Instance De Instancia e dê uma relida nestes conceitos antes de continuar.
(NameSpace) (Classe)
Para programadores não acostumados com a idéia de que uma
variável não tenha um tipo previamente definido, a seguir apresentamos
uma breve explicação do que vem a ser uma linguagem não tipada e das
parâmetro Parâmetro Temporária Temporária nomeada indexada implicações boas e mas que esta característica acarreta.
de método de Bloco de método de Bloco
Toda variável quando é declarada assume por definição que seu
valor é nil ou seja, seu valor é uma instancia de uma classe Undeclared-
Figura 6.1 Esquema de classes de armazenamento de variáveis no VisualWorks
Object.
Como podemos ver o esquema das variáveis é subdividido em
dois grandes grupos. O grupo das variáveis compartilhadas e o grupo
das variáveis privadas. Esta subdivisão se baseia no escopo das variá- 6.2 Não-Tipagem
veis. As variáveis privadas ainda são subdivididas em três grandes gru-
O que caracteriza uma linguagem como não tipada é o fato de
pos, as temporárias, variáveis class Instance e as variáveis de instancia.
não se declarar o tipo da variável no momento em que a mesma é declarada.
Mais adiante apresentaremos a descrição de cada um dos tipos de variá-
Em C, por exemplo, ao se declarar uma variável, procederíamos da
veis e de quando e porque devem ser utilizadas.
seguinte maneira:
Além de todo este esquema de variáveis, devemos ressaltar que
o Smalltalk é uma linguagem não tipada. Isso implica que ao se declarar int varInt;
uma variável não se especifica o tipo da mesma. Esta característica pode float varFloat;
parecer estranha a muitos programadores acostumados com linguagens Exemplo 6.1 Declaração de variáveis em C
tipadas como Pascal, porém esta é uma das principais características do
Smalltalk, e dá ao mesmo uma maleabilidade extrema. Na realidade, em Ou seja, as variáveis varInt e varFloat, já tem o seu tipo pré-defi-
Smalltalk toda variável é um ponteiro genérico, da mesma forma como nido de ante-mão. Esta característica possibilita que o compilador, em
em “C” temos o ponteiro do tipo void, que pode apontar para qualquer tempo de compilação, resolva as variáveis e aloque exatamente o
coisa. Mas isso não significa que aqueles dentre os leitores que têm aler- espaço necessários para abrigar estas variáveis. Isso torna o programa
gia ao uso de ponteiros precisem se preocupar: em Smalltalk você usa mais reduzido e rápido.

132 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 133


Variáveis Variáveis Privadas

Tomemos variáveis temporárias em Smalltalk para entender seu


mecanismo. Elas são declaradas da seguinte forma: 6.3 Variáveis Privadas
|varGenerica1 varGenerica2| Variáveis privadas são as variáveis que tem um escopo limitado
As variáveis tem apenas seus nomes definidos de ante-mão, localmente. Normalmente chamamos variáveis privadas aquelas que
impossibilitando que o compilador defina qual o montante de memória são acessíveis apenas dentro do escopo de um determinado objeto. Um
específico a ser destinado as mesmas em tempo de compilação. As vari- objeto geralmente possui seus atributos que são representados por vari-
áveis em Smalltalk, são então resolvidas em tempo de execução, ou áveis de instancia. Também possui métodos para perfazer ações que por
seja, quando a linha que atribui algum valor a variável é executada, o sua vez podem possuir argumentos e variáveis temporárias aos méto-
Smalltalk verifica o tanto de memória que ela necessita e aloca o mesmo dos. Dentro dos métodos podemos trabalhar com blocos, como por
na memória do computador. exemplo quando utilizamos coleções laços de repetição ou estruturas de
decisão. Para tais blocos ainda temos as variáveis temporárias aos blo-
cos e os argumentos que um bloco pode possuir. Em se tratando de clas-
Estratégia de À primeira vista, parece-nos que a estratégia adotada pelo
ses podemos possuir variáveis apenas acessíveis pelos métodos de
tipagem Smalltalk é menos eficiente que a adotada pelo C. Porém afirmar isto
classe.
seria se mostrar simplório. A intenção do Smalltalk a adotar a estratégia
não tipada reside na idéia de proporcionar uma imensa maleabilidade ao Todos estes tipos de variáveis acima apresentados compõem o
programador. Imagine a seguinte situação. Um programador escreve que chamamos de variáveis privadas. A seguir discutiremos cada um dos
uma classe em C++ que manipula números inteiros. Ele adota para esta tipos.
classe que todos os seus atributos internos serão inteiros, pois a classe
que escreve, manipulará números inteiros. Tudo funcionará bem e rapidi-
nho, porém, após terminar esta classe ele decide escrever outra, que 6.4 Variáveis de Instância
manipulará números em ponto flutuante. O que o programador C++
deverá fazer? Bem, ele praticamente terá que escrever a classe inteira Variáveis de instancia armazenam dados que são específicos a
novamente, pois a classe anteriormente escrita está amarrada a variá- cada objeto, ou seja, de cada instancia de uma determinada classe. Em
veis do tipo inteiro. orientação a objetos, podemos ver as variáveis de instancia, como os
“atributos” de um objeto.
No Smalltalk, devido ao fato de não haver tipagem, este fato não
ocorre e os ajustes a nova classe se fariam mínimos, pois os atributos da As variáveis de instancia se dividem em dois tipos. As variáveis
classe não tem um tipo previamente definido. Assim, podemos dizer que nomeadas e as indexadas.
o Smalltalk “troca” a velocidade de execução do C++ pela versatilidade No VisualWorks, para se declarar uma variável de instancia
que uma linguagem não tipada pode proporcionar. nomeadas, basta incluir seu nome entre as aspas a frente da palavra
Outro dado interessante sobre variáveis não tipadas é que a intanceVariableNames, e o campo indexedTipe seguida pelo símbolo
mesma variável pode assumir tipos distintos em tempos distintos, sem #none.
precisar redefini-la. Neste ponto vale relembrar um conceito básico de orientação a
objetos em Smalltalk. Como já sabemos, todas as variáveis são privadas
e todos os métodos são públicos. Logo, para acessar uma variável de

134 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 135


Variáveis Variáveis Temporárias a Métodos e Argumentos em Métodos

Smalltalk defineClass: #NameOfClass fico da instancia, podendo duas instancias da mesma classe tem número
superclass: #{NameOfSuperclass} de variáveis de instancia indexada distintos. Este tipo de variável é como
indexedType: #none um array, que relaciona um índice ao objeto que armazena.
private: false Vale resaltar que todas as variáveis de instancia indexadas de
instanceVariableNames: 'instVarName1 instVarName2' um objeto tem o mesmo tipo de valor, que é definido na criação da
classInstanceVariableNames: ''
classe. No campo indexedTipe especifique o tipo. Os mais comumente
imports: ''
utilizados são:
category: 'Collections-Sequenceable'
Exemplo 6.2 Definição de variáveis nomeadas
#object Para objetos genéricos
instancia de um objeto, faz-se necessário criar um método específico #byte Para bytes
para se encarregar desta tarefa. Por definição, na biblioteca de classes, Exemplo 6.4 Tipos das variáveis indexadas
estes métodos ficam agrupados no protocolo accessing e são como
Para acessar uma variável de instancia indexada, utilize a men-
segue.
sagem at: e para alterar ou incluir uma nova entrada utilize a mensagem
Imagine que na definição de uma classe que você está criando, at: put:
fez-se necessário criar uma variável de instancia chamada nomeDoCli-
Embora existam dois tipos distintos de variáveis de instancia,
ente. Os métodos de acesso para a variável seriam os seguintes:
faz-se necessário ressaltar que ambas podem conviver juntas, ou seja,
você pode Ter uma classe que tenha tanto variáveis de instancia nomea-
NomeDoCliente: umNome das como indexadas. Na figura 6.2 na página 138 vemos a definição da
“atualiza o nome do cliente”
classe OrderedCollection. Podemos ver que existem tanto variáveis de
nomeDoCliente := umNome
instancia nomeadas como indexadas.
nomeDoCliente
“retorna o nome do cliente”
^nomeDoCliente 6.5 Variáveis Temporárias a Métodos e
Exemplo 6.3 Criação dos métodos de acesso Argumentos em Métodos
Não existe problemas em se ter métodos e variáveis com o Variáveis temporárias são aquelas variáveis que tem um tempo
mesmo nome, e esta prática torna transparente a variável para quem for de vida curto. Para ser mais claro, são variáveis que só se fazem neces-
acessá-la. sárias durante um curto período de tempo seja dentro de um método
para operações intermediárias ou dentro de um bloco
É claro que as vezes você não deseja que sua variável de ins-
tancia seja acessada diretamente, neste caso, simplesmente não crie os A idéia de uma variável que seja criada, utilizada e depois des-
métodos de acesso para ela. truída serve para não sobrecarregar a memória do computador.
Já as variáveis indexadas não são nomeadas, e são acessadas Em métodos se declara variáveis temporárias, dentro de duas
através de um índice inteiro. O número de variáveis indexadas é especí- barras verticais, se existe mais que uma variável a ser declarada, seus

136 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 137


Variáveis Variável Temporárias dentro de Blocos e Argumentos em Blocos

Parâmetros, são variáveis que são passadas como argumentos


para métodos. Como o Smalltalk não é tipado, você pode usar o mesmo
argumento de uma mensagem para passar dois tipos distintos de objetos
em momentos distintos.
Porém vale lembrar que, embora você possa passar qualquer
coisa em um determinado argumento, provavelmente seu método terá
sido escrito esperando um determinado tipo de objeto. Se um tipo de
objeto não esperado é passado, isso pode gerar erros.
O importante à notar em argumentos é que eles são acessíveis
apenas para leitura. Você não pode atribuir nada a um argumento, ape-
nas ler o seu valor. Se tentarmos atribuir um dado a um argumento, o
compilador do Smalltalk reclama enviando a seguinte mensagem:
Attempt to store into argument

6.6 Variável Temporárias dentro de Blocos e


Argumentos em Blocos
Blocos são uma das maiores características do Smaltalk, eles
Figura 6.2 Declaração da classe OrderedCollection são variáveis que armazenam parcelas de código que podem ser avalia-
das (Mais detalhes a frente).
nomes devem ser separados simplesmente por espaços.O ciclo de vida
de uma variável temporária começa quando ela é declarada dentro de O interessante é que você pode declarar variáveis dentro dos
um bloco ou método, e termina quando um ou outro terminam. blocos e no momento em que for avaliar o bloco (utilizando value: , value:
value:, etc) passar os respectivos valores que as variáveis internas ao
alteraAlfa bloco devem assumir.
Esta característica é amplamente utilizada para criar laços de
"método para a alteração do Alfa do perceptron" repetição, operações em coleções e até estruturas de decisão. Abaixo
vemos alguns exemplos:
|novoAlfa|
Ainda podemos criar variáveis temporárias ao bloco. Isto se faz
novoAlfa := Dialog request: necessário quando o processamento dentro de um bloco gera valores
'Preencha o campo com um novo Alfa'. intermediários. A estrutura da declaração se dá semelhança do que faze-
self perceptron alfa: (novoAlfa asNumber). mos ao declarar variáveis temporárias em métodos. Abaixo listamos
Exemplo 6.5 Variável temporária dentro de um método outro exemplo:

138 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 139


Variáveis Variáveis de Instância de Classe (Class Instance Variables)

|bloco| mento para outro método, a única maneira de entrar dados dentro dos
bloco := [:arg1 | arg1 ** 2]. blocos é através de argumentos, visto que em outro método ele estará
bloco value: 10. fora do escopo em que foi criado.

|bloco resp|
bloco := [:arg1 :arg2 | arg1 + arg2]. 6.7 Variáveis de Instância de Classe
resp := bloco value: 10 value: 2.
(Class Instance Variables)
Exemplo 6.6 Variáveis temporárias em blocos
Uma variável tipo class instance armazena dados que variam
|bloco| com cada subclasse em uma hierarquia. A variável tipo class instance é
definida em uma classe e todas as suas subclasses a herdam, mas o
bloco :=[|resp respIntermed| valor é diferente e específico para cada sublcasse.
respIntermed := 256 / 17.
Não é muito comum a utilização de variáveis do tipo class ins-
resp := respIntermed asFloat.
]. tance, porém em alguns casos esta característica pode se mostrar bas-
bloco value. tante útil. Ela é declarada na definição da classe e só pode ser acessada
Exemplo 6.7 Outro exemplo de variáveis em blocos
por um método de classe. A seguir vemos um exemplo de como variáveis
tipo class instance podem ser utilizadas.
Outro dado interessante relacionando blocos e variáveis é o fato
de que dentro de um bloco as expressões internas “enxergam“ as variá-
veis externas dentro do método em que o bloco foi definido. Para ficar
mais claro, vamos lançar mão de um exemplo.
FALTA
"acessando variáveis em mesmo escopo dentro dos blocos"
"o resultado será o inteiro 110"
|index bloco|

index := 100.
[index + 10] value.
Exemplo 6.8 Mais um exemplo de variáveis em blocos
Exemplo 6.9 Utilização de variáveis tipo class instance
Você agora pode estar se perguntando porque então existe a
possibilidade de se passar argumentos para dentro de blocos? Os blocos
só conseguem ver variáveis que foram declaradas no mesmo escopo
que eles, isso quer dizer, que foram declaradas dentro do mesmo
método. Se existir a necessidade de se passar um bloco como argu-

140 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 141


Variáveis Variáveis Compartilhadas

O esquema de variáveis estáticas veio substituir vários outros


6.8 Variáveis Compartilhadas tipos de variáveis anteriormente utilizadas no VisualWorks, tais como as
Em versões anteriores ao VisualWorks 5i.1, existia um conceito variáveis pool, de classe e globais.
em que se podia definir uma variável como global. O VisualWorks regis-
trava a variável no System Dictionary e a variável era acessível a todos
os objetos dentro da imagem.
Com a inclusão do conceito de NameSpaces (Visto mais a frente
neste capítulo), o dicionário Smalltalk se transformou em um NameS-
pace. Ainda podemos definir variáveis e registra-las no system dictionary
porém apenas os objetos que estiverem dentro do NameSpace Smalltalk
terão acesso a ela.
Por conveniencia, ainda hoje oVisualWorks pergunta se você
deseja declarar a variável como global, mas o que ele faz realmente e
defini-la como uma variável estática a NameSpace , no NameSpace
Smalltalk. Aproveitando a conveniência adotada pelo VisualWorks vamos
Figura 6.3 Janela para a definição do tipo de variáveis
usar os termos global e estática a NameSpace como sinônimos.
É interessante ressaltar que você deve evitar ao máximo o uso Quando declaramos uma variável estática relativa a uma classe Variáveis
deste tipo de variável, principalmente se o conteúdo da mesma é de cru- o que estamos fazendo é mais ou menos como declarar uma variável de estáticas
cial importância ao sistema que você está desenvolvendo pois , como classe nas versões anteriores do VisualWorks.
qualquer objeto pode acessar variáveis globais, seu conteúdo pode ser
Quando herdamos uma classe que possua variáveis estáticas
alterado, prejudicando o funcionamento do que você está desenvol-
declaradas, elas também são herdadas.
vendo. Prime por utilizar variáveis encapsuladas dentro de seus objetos,
evitando assim problemas futuros. Agora, vamos ver como se declarar uma variável global direta-
mente. O Smalltalk tem um dicionário do sistema chamado Smalltalk.
Variáveis globais são de grande utilidade quando estamos vali-
dando algum código com o auxílio do WorkSpace. Note que uma vez que Por exemplo, para adicionar uma variável ao dicionário do sis-
você declara uma variável global ela continuará ocupando memória até tema procedemos da seguinte maneira:
que você explicitamente a remova. O VisualWorks fornece muitas facili-
dades para a criação de variáveis. Se as variáveis não são declaradas, Smalltalk at: #minhaVarGlobal put: ‘teste de variável
no momento em que for selecionado o item de menu accept para compi- global’
lar e salvar o código, uma janela será aberta perguntando como deve ser Para remover uma entrada do dicionário, utilize o método
declarada as variáveis ainda não declaradas. remove:
Smalltalk remove: #minhaVarGlobal

142 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 143


Variáveis Variáveis Especiais (self, super e thisContext)

O uso da variável especial self, permite ao programador indicar


6.9 Nomes para variáveis explicitamente que o método ou variável que deseja acessar foi imple-
Assim como se dá com os nomes de métodos, as variáveis pos- mentado no objeto corrente.
suem convenções em relação ao seus nomes, ligados diretamente ao
tipo de variável que ela irá representar. Intenda por tipo de variável se ela A variável super é uma referência para o objeto exatamente super
é local ou global. acima do objeto corrente na hierarquia de classes. O uso da variável
especial super se faz necessário, por exemplo, numa hierarquia de clas-
As convenções para nomes compostos por várias palavras são ses temos dois objetos, o objeto Retangulo e um objeto expecializado
as mesmas adotadas para os métodos. Os nomes também devem ser chamado Quadrado. Sabemos que um quadrado é um caso especial de
auto-elucidativos e não deve se poupar no tamanho do nome em detri- um retangulo. Definimos um método chamado tipoDoObjeto na classe
mento da sua entendibilidade. retangulo que retornará quando for invocado a string ‘retangulo’. O
A novidade está no fato das variáveis locais assumirem a pri- mesmo método será reescrito na subclasse Quadrado e retornará a
meira letra em minúsculo e para as variáveis globais assumirem a pri- string ‘quadrado’. Imagine agora outro método que retorne a hierarquia
meira letra em maiúsculo. do objeto quadrado. Criamos um método chamado mostraHierarquia que
As variáveis Globais e Locais ainda são subdivididas em algu- deverá retornar a hierarquia completa do objeto quadrado , ou seja, que
mas outras classes com algumas características distintas. Os subtipos o quadrado também é um retângulo. Já temos os métodos que nos retor-
serão cobertos nos próximos tópicos. nam quais os tipos dos objetos (tipo), mas como reescrevemos este
método na classe quadrado, a definição anterior do método em retangulo
Uma boa prática que eu adotei e se mostra muito útil em meus é perdida. Como a variável especial super nos fornece uma referência
programas é por prefixos as variáveis dependendo da função da mesma. um nível acima do objeto corrente na hierarquia de classes, podemos
Sita-se livre para utilizar qualquer técnica de nomenclatura adicional que fazer uso dela para executar o método Retangulo>>tipo ao invés do
você desejar. método quadrado>>tipo. thisContext

A variável especial thisContext é raramente utilizada durante o thisContext


6.10 Variáveis Especiais (self, super e thisContext) desenvolvimento de uma aplicação. Ela é uma referência para a pilha de
As variáveis especiais aqui descritas, são designadas na litera- contexto do processo corrente. É mais utilizada pelos sistemas de exce-
tura, também como pseudovariáveis. Como na documentação do Visu- ção e degugação.
alWorks, devido ao fato de outros objetos também receberem a
denominação de pseudovariáveis, optaremos por chama-las apenas de
variáveis especiais.

self A variável especial self mantém uma referência para o objeto


que está executando a mensagem corrente.

144 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 145


Variáveis

Capítulo 7 %ORFRVHVWUXWXUDV
GHFRQWUROHH
VHOHomR

Neste capítulo trataremos de dois assuntos de suma importância


para o Smalltalk: blocos e estruturas de controle e seleção. Iniciaremos
apresentando o conceito de blocos, qual a sua utilidade e onde devemos e
podemos utiliza-los. A seguir apresentaremos como Smalltalk suporta
estruturas de controle e seleção e por fim apresentaremos algumas estru-
turas de controle e seleção sobre coleções.

7.1 Blocos
Blocos foram pela primeira vez abordados no capítulo anterior no
momento em que falamos como funcionava seu mecanismo de variáveis.
Mas o conceito de blocos é muito mais amplo. Eles são usados extensiva-
mente nas estruturas condicionais e de repetição, em operações sobre
coleções controle de exceções, na criação e controle de processos e tam-
bém no mecanismo de tratamento de erros.
Basicamente, são parcelas de código Smalltalk, que podem ser
passadas como parâmetros para métodos e avaliadas a qualquer
momento. Dentro de um bloco qualquer tipo de expressão é aceita, inclu-

146 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Blocos, estruturas de controle e seleção Estruturas de controle e seleção

sive outros blocos. Eles também são extensivamente utilizados para se |bloco|
trabalhar com processos. "o resultado deste exemplo sera o valor da ultima expressão: 22"
Blocos são instancias da classe BlockClosure, e, como tudo no bloco := [
Smalltalk, subclasse de Object. Eles podem ser construídos diretamente 10 + 10.
apenas agrupando expressões entre os símbolos “[ ]” 20 + 2.
].
bloco value.
Funciona- Os blocos armazemam parcelas de código a serem executadas.
Exemplo 7.1 Retorna o resultado da operação matemática.
mento dos Mas para executar o conteúdo de um bloco precisamos explicitamente
blocos enviar uma mensagem ao bloco informando-o para que se execute. Blo-
|bloco|
cos aceitam uma grande diversidade de mensagens para executar sua
"o resultado deste exemplo será o valor da última expressão, no
validação, como podemos ver na lista de métodos abaixo:
caso, true"
•value bloco := [
•value: 10 + 10.
•value: value: 10 = 10.
•value: value: value: ].
•valueWithArguments bloco value.
•valueWithExit Exemplo 7.2 Retorna o resultado da comparação.
Caso um bloco seja encontrado durante a avaliação de um
que a mensagem de avaliação para blocos com mais de três argumentos
método e ele não receber uma das mensagens acima, ele simplesmente
(valueWithArguments:) receber como parâmetro um array de no máximo
será ignorado.
255 posições.
Partindo-se do princípio de que para avaliar um bloco precisa-
mos enviar uma mensagem para ele e de que todo método vai retornar
um objeto, é de se esperar algum retorno da avaliação do bloco. Mas o
7.2 Estruturas de controle e seleção
que exatamente ?
Por definição, os blocos sempre retornam a valor da última Estruturas de controle e seleção são geralmente implementadas
expressão avaliada. Abaixo dois exemplos de blocos. O retorno forne- utilizando envio de mensagens a instâncias das classes Number, Inte-
cido pela avaliação de cada bloco está em forma de comentário. ger, True, False, BlockClosure, e a praticamente todas as classes que
representam coleções.
Argumentos O esquema de argumentos e variáveis em um bloco já foram Existem as estruturas de seleção que são implementadas nas
e variáveis discutidos nos capítulos anteriores. Creio que o único dado relevante que classes True e False. Laços de repetição condicionais implementados a
foi deixado de lado anteriormente a esse respeito é o fato de que um partir também das classes True e False, laços de interação numérica
bloco aceita no máximo 255 argumentos. Este limite se dá pelo fato de implementados a partir das classes que representam os números e por
fim estruturas de interação sobre coleções, implementadas sobre pratica-
mente todas as classes que representam coleções.

148 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 149


Blocos, estruturas de controle e seleção Estruturas de controle e seleção

Laços de Esse tipo de laço de repetição corresponde aos laços tipo for "mostra o valor da contagem no Transcript"
iteração presentes em outras linguagem de programação. Em Smalltalk, eles são 1 to: 100 by: 5 do: [: cont |
numérica implementados nas classes da hierarquia de números e possuem basi- Transcript show: (cont printString)
camente 3 formas: ]
• timesRepeat: Exemplo 7.4 Iteração com passo definido pelo programador
• to:by:do:
• to:do: "mostra o valor da contagem no Transcript"
A mensagem timesRepeat deve ser enviada a um inteiro e
100 to: 200 do: [: cont |Transcript show: (cont printString)]
recebe como argumento um bloco. Os comandos contidos dentro do
Exemplo 7.5 Laço com limites definidos pelo programador
bloco serão então executados tantas vezes quanto for o valor do inteiro.
Desta forma se enviarmos a mensagem timesRepeat: ao inteiro 3, o
Repetições condicionais são laços que são executados Laços de
bloco passado como argumento será executado 3 vezes. No exemplo 7.3
enquanto uma condição é satisfeita. No Smalltalk, estes laços são imple- repetição
na página 150 a seguir apresentamos um exemplo de laço utilizando
mentados por mensagens enviadas a instâncias da classe BlockClo- condicionais
esta mensagem.
sure. Existem 5 tipos de laços, representados na tabela 7.1.
"Escreve 10 vezes Smalltalk no Transcript"
método descrição
10 timesRepeat: [Transcript show: ’Smalltalk’] repeat Repete continuamente até que o bloco force a saída
Exemplo 7.3 Forma mais simples de uma estrutura de repetição usando mensagens whileTrue Repete enquanto o bloco retornar verdadeiro. Teste no final da itera-
ção
A mensagem to:by:do: também é uma variante do laço for
whileFlase Repete enquanto o bloco retornar falso. Teste no final da iteração
onde podemos indicar qual o passo a ser adotado durante as iterações
do laço. Ela deve ser enviada a um inteiro recebendo como argumentos whileTrue: Repete enquanto o bloco retornar verdadeiro. Teste no início da itera-
ção
outro inteiro indicando qual o ponto de parada, outro inteiro indicando o
passo a ser adotado e um bloco contendo os comandos a serem repeti- whileFalse: Repete enquanto o bloco retornar verdadeiro. Teste no início da itera-
dos pelo laço. O bloco a ser passado deve esperar um argumento (como ção
vimos no capítulo referente a variáveis). Este argumento conterá o valor Tabela 7.1 Tipos de laços condicionais
atual da contagem, e mesmo que não seja usado deve ser declarado. No Os métodos repeat, whileFalse e whileTrue são mensa-
exemplo 7.4 a seguir apresentamos um laço de repetição utilizando a gens enviadas a um bloco e não possuem argumentos.
mensagem to:by:do:.
Os métodos whileTrue: e whileFalse: são também méto-
Por último veremos o laço implementado pela mensagem dos enviados a um bloco mas tem como argumento outro bloco, sendo
to:do:. Este é uma versão simplificada do laço implementado pela que o bloco que recebe a mensagem é testado a cada nova iteração e é
mensagem to:by:do:. A diferença está no fato de que o passo é sem- a condição de parada.
pre constante e de tamanho 1.

150 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 151


Blocos, estruturas de controle e seleção Estruturas de controle e seleção

O funcionamento de ambos os 5 laços de repetição condicionais Outro dado interessante, é que as seleções condicionais são,
é bem simples, sendo inclusive ‘whileTrue’ e ‘whileFalse’ definidos em como tudo termos de estrutura de controle da linguagem em Smalltalk,
relação aos métodos whileTrue: e whileFalse:, respectivamente. mensagens e são definidas na classe Boolean. Boolean é uma classe
Eles usam os conceitos de avaliação de blocos exaustivamente. Para dar abstrata e superclasse de outras duas, a classe True e classe False,
uma olhada na implementação, selecione a classe BlockClosure e pro- onde são implementados os métodos de seleção condicional descritos
tocolo controlling. Vale a pena dar uma olhadinha. abaixo:
No exemplo 7.6 vemos um trecho de código para cada tipo de • ifTrue:
laço condicional. • ifFalse:
• ifTrue: ifFalse:
"exemplo de utilização do método whileTrue" • ifFalse: ifTrue:
|c| Como o funcionamento destes métodos é intuitivo, apresenta-
c := 0. mos no exemplo 7.7 diretamente alguns trechos de código para o leitor
[Transcript show: ('numero' , c printString ).
se familiarizar.
Transcript cr.
c := c + 1.
c < 10] whileTrue. "exemplo de utilização da mensagem ifFalse:"

"exemplo de utilização od método whileFalse" |exp|


|c|
c := 0. exp := 10 < 3.
[Transcript show: ('numero' , c printString ). exp ifFalse: [Transcript show: ’A expressão era falsa’].
Transcript cr.
c := c + 1. "exemplo de utilização da mensagem ifTrue: ifFalse:"
c >= 10] whileFalse. |exp|

"exemplo de utilização do método whileTrue:" exp := 10 < 3.


|c| exp ifTrue : [Transcript show: ‘A expressão era verdadeira’]
c := 0. ifFalse: [Transcript show: ‘A expressão era falsa’].
[ c > 10] whileTrue: [c := c + 1]
Exemplo 7.6 Trechos de código para os diferentes tipos de laço condicional Exemplo 7.7 Utilização de mensagens de seleção condicional

Note que as mensagens de seleção condicional devem ser envi-


Seleções As seleções condicionais, ou como são comumente conhecidas,
adas a uma instancia de True ou False. Isso significa que qualquer
condicionais as estruturas if, são ligeiramente diferentes em Smalltalk, em compara-
expressão que retorne uma instância de umas destas duas classes pode,
ção com as outras linguagens de programação. Em primeiro lugar, não
potencialmente receber uma mensagem de seleção condicional. Isto
existe a estrutura else, mas sem prejuízo para a linguagem, pois é possí-
torna as possibilidades de você construir código condicional em Smalltalk
vel simular seu funcionamento.

152 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 153


Blocos, estruturas de controle e seleção Iterações sobre Coleções

extremamente flexíveis e facilita muito a criação de código, simples, intui- "exemplo de detect: "
tivo e compacto. #[1 2 3 4 5 6 76 8 9 ] detect: [: each| each == 2]
Exemplo 7.9 Código para encontrar um elemento igual a 2 numa lista

7.3 Iterações sobre Coleções O método select: permite filtrarmos os itens de uma coleção select:
criando uma nova coleção. Por exemplo podemos utilizar este método
A parte da hierarquia de classes que define a grande variedade
para sabermos quantos espaços possui uma string. este exemplo é mos-
de coleções é sem sombra de dúvida um dos pontos fortes do Smalltalk.
trado a seguir:
Uma das características que fazem-na tão boa é a facilidade de manipu-
lação de dados conferida por alguns métodos implementados nestas
"exemplo de select:"
classes. A seguir apresentaremos algumas destas características e em
('Smalltalk é uma ótima linguagem OO' select: [:char|
seguida alguns exemplos.
char == (Character space) ]
Existem vários métodos para realizar a iteração sobre os objetos ) size.
contidos nas coleções. Abaixo apresentamos uma lista deles: Exemplo 7.10 Código que retorna o número de caracteres-espaço em uma string
•do:
•detect: O método reject: é exatamente o oposto ao select:. Veja- reject:
•select: mos o mesmo exemplo anterior apenas alterando a mensagem e tere-
•reject: mos a contagem de todos os caracteres na string que não são espaços.
•collect:
"exemplo de reject:"
do: O método do: avalia o bloco passado como argumento ao ('Smalltalk é uma ótima linguagem OO' reject: [:char|
método para cada elemento do conjunto. O bloco deve possuir um argu- char == (Character space) ]
mento também, que referenciará o item da coleção selecionado a cada ) size.
iteração. Exemplo 7.11 Código que retorna o número de caracteres não brancos em uma string

"exemplo de utilização do método do:" O método ‘collect:’ permite-nos criar uma nova coleção a partir collect:
#[1 2 2 3 4 5] do: [: each| da coleção original ajustada a uma regra de validação passada dentro do
Transcript show: (each printString)] bloco que é esperado como argumento. O seguinte exemplo mostra
Exemplo 7.8 Código para impressão de todos os elementos de uma lista como podemos passar toda uma string para maiúsculas.

detect: O método detect: avalia uma expressão contida no bloco pas- "exemplo de collect:"
sado como argumento ao método para cada elemento da coleção até 'Smalltalk é simples' collect: [:char | char asUppercase]
encontrar um elemento que satisfaça o bloco. Neste caso o elemento Exemplo 7.12 Código que retorna uma nova string contendo a string receptora em maiúsculas
que satisfez a expressão contida no bloco é retornado, caso nenhum ele-
mento da coleção satisfassa a expressão, um erro é gerado.

154 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 155


Blocos, estruturas de controle e seleção

7.4 Exercícios
1. Faça um programa no workspace que calcula o fatorial de um
Capítulo 8 0DQLSXODomRGHDUTXLYRV
número. Teste-o para números grandes como por exemplo 100.
2. Crie um método que calcule o fatorial de maneira recurciva. Lembre-
HHVWUXWXUDVGHDFHVVR
VHTHQFLDO
se da classe criada anteriormente.
3. Qual é o número máximo de argumentos que podem ser passados
para um argumento ? De que forma eles são passados ?
4. Nos exercícios do capítulo 4 propomos uma questão onde gostaria-
mos de saber como criar matrizes apenas utilizando arrays. Agora
crie uma classe que implemente esta matriz e crie alguns métodos
úteis tais como calcular a matriz inverça, métodos para operações
como multiplicação e soma de matrizes, etc.
5. Navegue pela hierarquia de classes de coleções e inspecione seus
métodos a procura de outros métodos para iteração de coleções.

Neste capítulo apresentaremos o mecanismo do Smalltalk para


manipular arquivos e para iterar sobre coleções armazenadas em estrutu-
ras de acesso seqüencial, conhecidas como data streams. O enfoque do
estudo estará centrado sob as hierarquias de classes de duas classes, a
classe Stream e a classe Filename. O acesso ao sistema de arquivos
será também abordado em detalhes, sendo apresentados todos os méto-
dos para a criação, exclusão, alteração, inserção, leitura, renomeação,
agragação e movimentação de arquivos/diretórios. Veremos que a referên-
cia ao sistema de arquivos é feita por instancias da classe Filename mas
que a manipulação das mesmas se dá através de instancias da classe
Stream.

8.1 Introdução
Como o sistema de arquivos é muito particular à cada sistema
operacional, o Smalltalk implementa classes especializadas a partir da
classe Filename para cada sistema operacional. Abordaremos as referen-
tes aos sistemas Windows e Unix/Linux.

156 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Manipulação de arquivos e estruturas de acesso seqüencial Streams

Também veremos a utilização de instâncias de Stream para a ExternalReadWriteStream, é responsável pela criação de streams para
manipulação seqüencial de coleções, sejam elas, instâncias de Ordered- a manipulação de arquivos.
Collection, Array, ByteArray, String ou do conteúdo de arquivos em Nesta primeira parte do capítulo daremos ênfase ao primeiro dos
disco lidos para a memória. ramos, deixando o segundo para a seção que trata especificamente de
arquivos.

8.2 Streams Para as subclasses de PosicionableStream existem duas Criando


À primeira vista, instancias da classe Stream não parecem de maneiras para a criação de instâncias. Deixaremos para ver como cirar instâncias de
modo algum úteis. O que elas fazem ? Permitem que se leia e escreva uma stream para manipulação de arquivos mais a frente neste capítulo. Stream
dados em uma coleção, arquivo ou string de maneira ordenada. E dai ? A A primeira das maneiras é instanciar uma stream a partir de uma
gama de coleções de dados do Smalltalk é muito rica e temos por exem- das subclasses de Stream utilizando a mensagem on: ou with:. Isso
plo as OrderedCollections que nos permitem manipular nossas cole- pode ser feito das maneiras demonstradas no exemplo 8.1. No primeiro
coes de objetos de uma maneira bem eficiente.
De fato, streams encontram aplicações principalmente na mani- |stream arr|
pulação de coleções de tamanho fixo (ou melhor, coleções seqüenciais,
arr := #(1 2 3 4 5).
em que exista a idéia de ordem entre os dados), manipulando strings
stream := WriteStream with: arr.
onde podemos observar ganhos reais em performance e também em
stream nextPut: 6.
arquivos. Aliás, como veremos mais a frente neste capítulo, toda e qual- stream contents. "---> #(1 2 3 4 5 6)"
quer manipulação de arquivos se dá apenas de uma forma, que é atra-
vés da criação de uma stream sobre o mesmo. |stream arr|
O mecanismo de manipulação de arquivos do smalltalk é bem
consistente e estrurado como poderemos ver, e isso se dá graças a utili- arr := #(1 2 3 4 5).
zação de streams. stream := WriteStream on: arr.
stream nextPut: 6.
stream contents. "---> #(6)"
Streams Ao observarmos a hierarquia de classes de Stream podemos
Exemplo 8.1
poscionáveis ver dois ramos bem distintos. Um que se ramifica a partir de Positiona-
e streams bleStream e outro a partir de ExternalStream. O primeiro dos ramos exemplo, criamos uma stream utilizando a mensagem with: e pas-
externas contendo principalmente as classes ReadStream, WriteStream e Rea- sando o Array previamente criado como argumento. Como podemos ver
dWriteStream definem as streams que implementam a idéia de sequên- no comentário ao lado da última instrução, os dados originais da coleção
cia e posição. E a partir destas classes que instanciamos streams para a são mantidos e o novo dado adicionado é posto ao final da coleção. Já
manipulação de strings e coleções como os arrays. no segundo exemplo onde usamos a mensagem on:, vemos que o con-
O segundo ramo, contento principalmente as classes External- teúdo anterior da coleção é descartado.
ReadStream, ExternalWriteStream, ExternalReadAppendStream e

158 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 159


Manipulação de arquivos e estruturas de acesso seqüencial Streams

A outra forma de se criar stream consistem no envio de uma Ao abrirmos a stream para leitura vemos que a posição inicial é
mensagem para a coleção. Existem quatro mensagens definidas na zero, sendo que ao enviarmos a mensagem next, o dado na posição 1
classe SequenceableCollection (que também é superclasse de String é retornado.
além de ser de Array e OrderedCollection) que nos permitem cirar stre-
ams. São elas: |stream arr|
readStream - cria uma stream a partir da coleção especifi-
arr := #(1 2 3 4 5).
cada, apenas para leitura
stream := arr readWriteStream.
writeStream - cria uma stream a partir da coleção especifi- stream next. "---> 1"
cada, apenas para escrita e exclui os dados pré-existentes na coleção. stream nextPut: 6.
stream contents. "---> #(1 6 3 4 5)"
readWriteStream - cria uma stream a parir da coleção
especificada para leitura e escrita e mantém os dados originais da cole- Exemplo 8.4 Criação de uma stream para leitura e escrita e inclusão de um novo elemento
ção posicionando a stream para escrita no seu final.
Note que neste exemplo o elemento na posição 2 foi sobrescrito,
newReadWriteStream- cria uma stream a parir da coleção pois mandamos que o SmallInteger fosse adicionado na próxima posicao
especificada para leitura e escrita e exclui os dados originais da coleção. da stream que no caso era a 2, já que havíamos posicionado a stream na
primeira posição com a mensagem next.
|stream arr|
|stream arr|
arr := #(1 2 3 4 5).
stream := arr writeStream. arr := #(1 2 3 4 5).
stream contents. "---> #()" stream := arr newReadWriteStream.
Exemplo 8.2 Criação de uma stream habilitada para escrita stream next. "---> nil"
stream nextPut:10.
Neste exemplo podemos ver que o conteúdo da coleção é exclu- stream nextPut:11.
ído quando criamos a stream para escrita. stream reset.
stream next. "---> 10"
|stream arr| Exemplo 8.5 Usando um array como novo stream de leitura-escrita apagamos seu conteúdo

arr := #(1 2 3 4 5). No exemplo 8.5 podemos ver que a mensagem newRea-
stream := arr readStream. dWriteStream exclui o conteúdo anterior da coleção. Nos exemplos
stream next. "---> 1 " anteriores apareceram várias mensagens que ainda não foram devida-
stream next. "---> 2" mente especificadas. Não se preocupe, elas serão cobertas ao longo do
Exemplo 8.3 Criação de uma stream somente para leitura capítulo.

160 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 161


Manipulação de arquivos e estruturas de acesso seqüencial Streams

Streams As facilidades de se utilizar streams para a manipulação de cole- Quando estamos trabalhando com strings é que vemos como as Streams
sobre ções são muitas. Quando você teve um primeiro contato com coleções streams podem ser úteis. Por exemplo, nos casos onde desejamos fazer sobre strings
coleções em Smalltalk, garantidamente uma das primeiras estruturas de dados pesquisas sobre strings para encontrar um determinado caractere. Pode
que você utilizou foi o Array. Ele tem uma limitação muito séria, seu parecer besteira, mas essa é uma das aplicações que mais ocorrem em
tamanho é fixo. Ao utilizarmos uma stream para manipular os dados de programação. Utilizando os métodos tradicionais implementados na
um array adicionamos a capacidade ao array de almentar o seu tamanho classe string você terá um bocado de trabalho, já lançando mão da solu-
diretamente. A alternativa sem a utilização de streams é cirar um novo ção de streams, boa parte do trabalho estará otilizado. O programador
array contendo todos os dados antigos e o novo dado. Outra grande faci- que alguma vez escreveu um scanner em uma linguagem de programa-
lidade é você não ter de se preocupar com os índices criando os fatidicos ção sabe do que estou falando. É realmente um saco escrever código
laços de repetição com a famosa variável “i” para incrementar o índice. para manter um pesquisa um pouco mais complexa em uma string.
As streams em geral, tem a facilidade de sempre adicionar os novos Outra grande vantagem da manipulação de strings através de
dados ao seu final, porém caso seja necessária uma alteração de algum streams está centrada na performance. Quando concatenamos duas
dado do meio da stream, também é possível perfze-lo. strings usando a mensagem binária "," , em geral o que acontece é que
O seguinte código mostra como podemos adicionar novos dados uma nova string é criada contendo os dados das duas strings pré-exis-
a uma coleção pré-existente. tentes. A solução da classe Stream para isso é em geral mais rápida,
mas pense bem, a vantagem está no fato de stream nao criar um novo
|stream arr| objeto, mas sim apenas aumentá-lo. Para poucas concatenações de
strings o método "," é bem recomendável, mas quando o número de con-
arr := Array new:1. catenações cresce e se deseja performance o uso de uma stream é
arr at:1 put: 1. indispensável. Vale resaltar que quando formos utilizar streams para
stream := arr readWriteStream. fazer concatenações de strings devemos ter uma string de um tamanho
stream setToEnd. bom como string inicial a partir da qual criamos a stream. Se criarmos
stream nextPut:6. uma stream a partir de uma string vazia, ela deverá crescer várias vezes
Exemplo 8.6 Incluindo dados em um stream préexistente para perfazer as concatenações. Neste caso, o processo será muito cus-
toso. Uma boa aplicação de concatenação de strings via stream é
Além disso, vale saber que quando criamos uma stream a partir
quando estamos compondo querys em SQL. O número de concatena-
de uma coleção, ela guarda qual é o tipo de coleção sob a qual foi criada,
ções é muito grande em geral. No exemplo 8.7 na página 164 apresenta-
desta forma podemos utilizar a mensagem contents que nos retornará
mos um exemplo para a criação de uma query.
uma nova coleção do mesmo tipo que a original e com as alterações fei-
tas pela stream. As mensagens para aproveitar estas características são:
stream contents.
Nesta seção as coisas se tornarão mais claras. Nos exemplos Lendo,
stream contentsSpecies. anteriores vimos como criar streams e também as peculiaridades ineren- escrevendo e
tes a streams sobre coleções e strings. Como o funcionamento de leitura, posicio-
A mensagem contentsSpecies retorna a classe da cole- escrita e reposicionamento em stream é de certa forma trivial, limitar-nos- nando uma
ção sobre a qual a stream foi criada. hemos a apresentar os principais métodos relativos a tais operações e stream
uma breve descrição sobre cada um deles. Para fomentar o seu aprendi-

162 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 163


Manipulação de arquivos e estruturas de acesso seqüencial Streams

queryIgualPara: tabela da stream.


campoCondicao: campo • through: - retorna todos os objetos incluindo o da posição
dadoCondicao: dado atual até encontrar uma ocorrência do objeto especificado pelo
argumento. Caso nenhuma ocorrência do objeto seja encon-
|stream| trada, retorna todos até o final da stream.
• throughAll: - o mesmo que o método anterior só que o
stream := (String new: 100) writeStream. argumento é uma coleção de objetos.
stream nextPutAll: 'SELECT * FROM'; • contents - retorna todos os objetos da stream em forma de
space; coleção igual a coleção a partir da qual foi criada a stream.
nextPutAll: (tabela printString);
space; • nextPut: - inclui o objeto passado por argumento no final da Escrevendo
nextPutAll: 'WHERE'; stream. Se a stream estiver operando sobre uma string, os
space; objetos deverão ser caracteres.
nextPutAll: (campo printString);
• nextPutAll: - inclui a coleção de objetos passada como
space;
argumento ao final da stream. Se a stream estiver operando
nextPutAll: '=';
sobre uma string, o argumento deverá ser uma string.
space;
nextPutAll: (dado printString). • print: - executa o método printString do objeto passado
^stream contents. como argumento e adiciona a string retornada ao final da
stream.
Exemplo 8.7 Código para uma query SQL usando streams
• cr - carriage return - adiciona um enter à stream
zado, sugiro fortemente que você faça os exercícios do final do capítulo • tab - adiciona uma tabulação a stream
para garantir que o conceito se consolide em sua cabeça. • tab: - adiciona o número especificado pelo argumento de
tabulações a streai
Lendo • next- retorna o próximo objeto da stream e avança uma • crtab - adiciona um enter e em seguda um tab a stream
posição. No caso de Streams sobre Strings, retorna um • crtab: - adiciona um enter seguido de tabulações em número
caractere. especificado pelo argumento
• next: - retorna os próximos objetos. O número de objetos é • space - adiciona um caractere de espaço à stream
indicado pelo argumento. Se o número especificado pelo • lf - adiciona um caractere de retorno de carro (line feed) à
argumento transpor o último objeto, um erro é gerado stream
• nextAvaliable: - faz o mesmo que o método anterior,
porém se o argumento transpor o último objeto, retorna apenas • atEnd - retorna um booleano indicando se a stream está ou Posicionando
os existentes até o fim da stream. não posicionada no final
• upTo: - faz o mesmo que o método anterior porém não retorna • reset - retorna a stream para o início, fazendo o seu ponteiro
o primeiro objeto. de leitura/escrita apontar para o seu primeiro caractere
• upToEnd - retorna todos os objetos da posição atual até o final • setToEnd - posiciona a stream no final.

164 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 165


Manipulação de arquivos e estruturas de acesso seqüencial A classe Filename e Streams sobre arquivos

• readPosition - indica qual a posição de leitura. Retorna um nalWriteStream, ExternalReadWriteStream e ExternalReadAppendS-


inteiro. tream. Porém não criamos diretamente instâncias destas classes. O que
• writePosition - indica qual a posição em que será é costumeiro fazer, é enviar uma mensagem a uma instância de File-
realizada a próxima escrita. Retorna um inteiro name para que o arquivo seja aberto de maneira adequada.
• position - indica qual a posição atual da stream Para isso é necessário primeiro criar uma instância de Filename
• position: - seta a posição da stream para a posição que representa o arquivo externo. Uma instância de Filename é o mani-
passada como argumento pulador de arquivo ou handle deste arquivo e serve para interagir com o
• skip: - avança a stream um número específicado pelo argu- sistema operacional e referenciar um arquivo externo, não importa seu
mento para a frente tipo. Para criar instâncias da classe Filename existem duas abordagens
• skipSeparators - pula separadores, que no caso são: tab, básicas. Você pode mandar uma mensagem para a classe Filename ou
space, lf e cr. Permite, por exemplo que você leia um arquivo mandar uma mensagem para uma string, conforme mostra o exemplo
texto até o fim de uma linha e daí a partir do primeiro caracter útil 8.8.
do início da próxima linha
• skipUpTo: - posiciona a stream exatamente antes do objeto |meuArq|
especificado pelo argumento meuArq := Filename named: 'C:\vw5i.3nc\image\arquivo.txt'.
• skipThrough: - faz o mesmo que o objeto anterior porém "Cria uma instância de Filename sobre o arquivo passado como argu-
posicionando após o objeto especificado mento ao método named:"
Além destes métodos, existem ainda outros implementados por
meuArq := 'C:\vw5i.3nc\image\arquivo.txt' asFilename.
streams externas para mudar o modo de operação para permitir operar
"Produz o mesmo resultado, só que usando um método implementado por
sobre arquivos binários, como imagens, além de métodos para abrir e String"
fechar arquivos, que veremos adiante.
Exemplo 8.8 Duas formas de criar um manipulador para um arquivo a partir de seu nome

No caso de existir um diretório específico onde se deseja criar


8.3 A classe Filename e Streams sobre arquivos um arquivo, existem duas abordagens para fazer isso. Se o diretório já foi
inicializado como um Filename, você pode construir outro filename para
Em termos gerais, todas as referências a arquivos e diretórios
o arquivo. Se o diretório é uma string, você deve concatenar o diretório
em Smalltalk, são necessáriamente instancias da classe Filename. É
com o nome do arquivo e dai criar um Filename. O exemplo 8.9 mostra
importante citar para que não pairem dúvidas que uma instancia de File-
as duas formas.
name é apenas uma referencia a um arquivo ou diretório. Para que pos-
samos manipular o filename tal como apra escrever no arquivo, ler O seguinte exemplo cria um filename a partir de um array de
dados, adicionar novos dados ou excluir dados pre-existentes devemos strings contendo a unidade, os vários diretórios em ordem de aninha-
utilizar uma stream. As classes ReadStream, writeStream e ReadWriteS- mento e por último o nome do arquivo. Em geral eu implemento este
tream foram concebidas a principio para a malipulação de strings e cole- código, mostrado no exemplo 8.10, como um método nas minhas aplica-
ções. Então faz-se necessário uma outra gama de classes filhas de ções que manipulam arquivos pois ele facilita a criação de filenames no
Stream para manipular Arquivos. Elas são: ExternalReadStream, Exter-

166 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 167


Manipulação de arquivos e estruturas de acesso seqüencial A classe Filename e Streams sobre arquivos

|filename nomeDoDir dirCaminhoStr| código deste exemplo num workspace e executá-lo passo a passo, ins-
pecionando os resultados para ver o que acontece.
dirCaminhoStr := 'C:\vw5i.3nc\image'.
nomeDoDir := dirCaminhoStr asFilename. |nomeArq caminhoArq|

"primeiro jeito" nomeArq := 'C:\vw5i.3nc\image\arquivo.txt' asFilename.


filename := nomeDoDir construct: 'arquivo.txt'. nomeArq directory.
filename := 'C:\vw5i.3nc\image\arquivo.txt' asFilename. nomeArq head.
nomeArq tail.
"segundo jeito"
filename := (dirCaminhoStr , caminhoArq := 'C:\vw5i.3nc\image\arquivo.txt'.
(String with: Filename separator), Filename breakup: caminhoArq.
'arq.txt'
) asFilename. Filename splitExtension: caminhoArq.
Filename splitPath: caminhoArq.
Exemplo 8.9 Duas formas de concatenar o caminho e o nome de um arquivo Exemplo 8.11 Manipulando o nome de um arquivo

local correto. De qualquer forma, serve como um exemplo para entender Como podemos ver e já foi citado, instâncias de Filename nada
o mecanismo de criação de refeências de arquivos. mais são que uma referência a um arquivo existente ou que será criado,
os manipuladores ou handles de arquivo. No final das contas você pode
|stream arrayDirNames| estar pensando por que criamos uma instância de um objeto apenas
para referênciar um arquivo que pode nem existir ainda. Por que não
arrayDirNames := #('c:' 'vwnc5i.3' 'image' 'arq.txt'). usamos uma string logo de uma vez já que os tais Filenames parecem
stream := (String new: 30) writeStream. tanto com elas ? A resposta é que os Filenames nos fornecem várias
arrayDirNames do:[:cada| capacidades para verificar dados do sistema de arquivos do sistema
streamnextPutAll: cada; operacional tal como se ele é case sensitive ou qual o sistema de arqui-
nextPut: Filename separator. vos tais como os famigerados FAT, FAT32, ou NTFS. Além disso, tam-
].
bém implementa as mensagens para a abertura do arquivo por ela
Filename named: stream contents.
referenciado, coisa que soaria mutio anti-OO de ser implementada na
Exemplo 8.10 Construindo o nome e caminho de arquivo a partir de seus elementos
classe String. Dessa forma, a classe Filename cria uma coisa extrema-
Uma instância de Filename parecem em muito com uma lista em mente importante: transparência a sistema operacional nas suas aplica-
LISP. Elas são compostas por um head (cabeça) e um tail (cauda). Onde ções. Mais a frente veremos estes métodos que justificam a existência
a cabeça é o caminho em que o arquivo se encontra e a cauda é o nome da classe Filename.
do arquivo. A classe Filename também implementa diversos métodos
para verificarmos as partes que compoem o caminho do arquivo. O
exemplo 8.11 mostra alguns destes métodos. Experimente digitar o

168 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 169


Manipulação de arquivos e estruturas de acesso seqüencial Finalmente Abrindo os Arquivos (e também fechando)

5. O método readAppendStream abre o arquivo para leitura e adi-


8.4 Finalmente Abrindo os Arquivos (e também ção de novos dados. A única diferença em relação ao item 4 é que se
fechando) o arquivo já existir seu conteúdo será deixado intocado.
Depois de termos criado uma referência ao arquivo que quere- 6. O método newReadWriteStream abre o arquivo para leitura e
escrita. Se o arquivo já exisitr seu conteúdo será excluído, e se não
mos manipular através da instanciação de um objeto a partir de File-
existir ele será criado. A stream pode ser posicionada em qualquer
name, podemos efetivamente abrir este arquivo e fazer coisas úteis com
lugar no arquivo para leitura e escrita.
ele.
7. O método readWriteStream é similar ao item 6, mas se o
Como em todas as linguagens de programação, o Smalltalk per- arquivo exisitr, seu conteúdo é deixado intocado.
mite que arquivos sejam manipulados de duas maneiras, no modo texto,
Após a abertura e manipulação do arquivo em Smalltalk, diferen-
onde os dados são sempre caracteres, e no modo binário onde manipu-
temente de muitas linguagens de programação, devemos explicitamente
lamos bits, bytes, words e longWords, que como sabemos são os bonitos
fecha-lo. Se não fizermos isso, a stream que manipula o arquivo perma-
nomes para 1, , 8, 16 e 32 bits.
necerá instanciada e conseqüentemente o arquivo ficará aberto. A per-
Para abrir um arquivo seja em que modo de manipulação for, manência do arquivo aberto implica em várias coisas, todas ruins. Os
basta que enviemos uma mensagem para o filename que o referencia. A sistemas operacionais de uma maneira geral, permitem um número
classe implementa 7 métodos para abertura de arquivos. Essas mensa- máximo de arquivos abertos no mesmo instante, se não fecharmos nos-
gens criarão uma stream instanciada a partir de uma das subclasses da sos arquivos corretamente, pode chegar um momento onde você queira
classe ExternalStream. Os tão esperados métodos para a abertura de abrir um arquivo e não consegue porque existem outros tantos abertos
arquivos são os seguintes: que você nem sabe. O outro grande problema de não se fechar um
1. O método readStream abre o arquivo referenciado pela instancia arquivo diz respeito à integridade de dados. Se você não fechar seus
de Filename para leitura. Mas o arquivo deve existir, caso ele nao arquivos e por exemplo a energia acabar, nada garante que os dados
exista, um erro será gerado. deles estarão seguros.
2. O método writeStream abre um arquivo para escrita. Se o Para fechar um arquivo, basta que seja enviada a mensagem
arquivo já existir todo o seu conteúdo será deletado e os novos dados close para a stream.
a serem inseridos começarão no início do arquivo. Se o arquivo ainda
não exsitir ele será criado como arquivo vazio. O código no exemplo 8.12 mostra como podemos criar um
3. O método appendStream abre o arquivo para adição de novos arquivo para escrita. Em seguida escreveremos algumas strings dentro
dados. Os novos dados serão sempre inseridos no final do arquivo, e dele e por fim, e não menos importante, vamos fechá-lo.
os dados pré-existentes serão deixados intocados. Caso o arquivo
não exista, ele será efetivamente criado. Os arquivos são sempre abertos em modo texto. Se necessitar- Arquivos
4. O método newReadAppendStream abre o arquivo para leitura e mos manipula-los de maneira binária, devemos enviar a mensagem não-textuais
adição de novos dados. Se o arquivo já existir, seu conteúdo será binary para a stream. A capacidade de trabalhar com arquivos em
deletado. Se o arquivo ainda não existir ele será criado. A stream forma binária, isto é, arquivos cujo conteúdo não são texto codificado em
pode ser posicionada em qualquer lugar no arquivo para leitura, mas ASCII é de extrema importância. É necessário trabalhar-se com arquivos
inserções serão feitas sempre no final do arquivo. em modo binário quando você precisar ler imagens, cujos pixels estão

170 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 171


Manipulação de arquivos e estruturas de acesso seqüencial Exercícios

|wrS | gramas gráficos XV ou gimp. Em ambiente Windows existem hoje vários


wrS := 'q:\arquivosSmall\arqu.ex' asFilename writeStream. programas gráficos que lêem e escrevem PGM.
wrS nextPutAll: 'as 3 mais do Brasil'; O formato PGM possui dois subformatos. Um, conhecido por
cr;tab; PGM ASCII contém todos os dados de imagem codificados em ASCII,
nextPutAll: 'Internética'. inclusive os valores dos pixeis, que são descritos por números inteiros
cr;tab;
em formato textual. Este gera arquivos imensos e não nos interessa aqui.
nextPutAll: 'Feiticeira'.
O outro, chamado PGM binário, é bem menor e possui duas partes: um
cr;tab;
nextPutAll: 'Tiazinha'. cabeçalho bem simples em ASCII, onde estão um string código ’P5’ indi-
wrS close. cando o formato (magic number), um comentário de uma linha, o número
Exemplo 8.12 Criando, escrevendo e fechando um arquivo texto
de tons de cinza e o tamanho X*Y da imagem. Depois disso, estão os
pixels da imagem, codificados de forma binária, 8 bits por pixel. Se você
geralmente armazenados de forma binária e também quando você for está trabalhando em Unix/Linux, experimente digitar man pgm em
desenvolver algum aplicativo que necessite ler ou gerar arquivos de uma janela de comando para ver a definição oficial do formato. Nós
dados de ou para um outro programa. No exemplo 8.13 vemos um vamos escrever um método que abre um arquivo, testa se é PGM biná-
código bastante simples, que cria um arquivo binário e escreve uma rio, lê o cabeçalho, cria uma instância de Depth8Image em Smalltalk do
string nele usando o método nextStringPut:. Observe que você tamanho certo, muda o modo do arquiivo para binário e lê os pixels do
não vai poder usar o métrodo nextPutAll: para coleções para arquivo. Feito isto, o método abre um inspetor sobre a imagem que leu.
escrever texto em um arquivo binário. Neste exemplo estamos usando uma instância da classe File-
Connection ao invés de Filename. Isto é outra forma de se fazer a aber-
|wrS | tura de um arquivo a um nível um pouco mais baixo. Aqui também
wrS := 'q:\arquivosSmall\arqu.ex' asFilename writeStream. usamos conceitos que você ainda não viu como mapa de cores para uma
wrS binary. imagem, mas que serão vistos adiante.
wrS nextStringPut: 'as 3 mais do Brasil';
wrS close.
Exemplo 8.13 Escrevendo texto em um arquivo em modo binário
8.5 Exercícios
O próximo exemplo é bem mais avançado. Ele mostra um trecho 1. Encontre a definição de um formato de arquivo texto não-proprietário,
de código para você ler um bitmap no formato .pgm binário. O formato como o formato RTF (Rich Text File) e crie um objeto capaz de ler um
PGM (Portable GrayMap) é um formato de imagens em tonalidades de arquivo .rtf gerado com algum editor de texto e dele extrair somente o
cinza que surgiu no ambiente Unix e hoje é largamente usado. Usamos texto, ignorando os comandos de formatação, bitmaps incluídos e
este formato no nosso exemplo porque ele é extremamente simples e outras coisas que haja lá dentro. Observe que para isso, você deve
dispensa as longas explicações que um exemplo baseado em formatos ler o arquivo em modo binário, já que muitos dos comandos e os bit-
mais conhecidos como BMP ou GIF necessitaria. Se você deseja criar ou maps estarão codificados de forma binária e não em ASCII, apesar
olhar uma imagem PGM em ambiente Unix/Linux, você pode usar os pro- de o arquivo ser de "texto".

172 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 173


Manipulação de arquivos e estruturas de acesso seqüencial Exercícios

|aStream dimX dimY magicNumber max imagem valor posi cores| 2. Procure a implementação da classe SortedCollection e analize a
implementação da mesma. Em seguida crie uma parcela de código
aStream := (ExternalReadStream on: (FileConnection que gere 10 números aleatoriamente no intrervalo de 1 a 10 e adici-
openFileNamed: 'imagem.pgm' mode: #readOnly one estes números a uma sorted colection. Por fim imprima seu resul-
creationRule: #noCreate)). tado no Transcript.
"Lê o magic number e testa se o arquivo é do formato certo"
magicNumber := aStream upTo: (Character cr).
(magicNumber = 'P5') ifFalse: [ aStream close.
self error: 'Formato errado'. ^nil.].
aStream skipSeparators.
"Vamos ler a linha de comentário e jogar fora"
aStream upTo: (Character cr). aStream skipSeparators.
"Vamos ler as dimensões X e Y da imagem"
dimX := Integer readFrom: aStream.
aStream skipSeparators.
dimY := Integer readFrom: aStream.
aStream skipSeparators.
"Vamos ler quantas tonalidades de cinza tem a imagem"
max := Integer readFrom: aStream. aStream next.
"Criamos a tabela de cores da imagem com base em max"
posi := 1. valor := 0. corres := Array new: (max + 1).
[valor < max]
whileTrue: [cores at: posicao put:
(ColorValue brightness:(valor/max)).
valor := valor + 1. posi := posi + 1].
"Passamos a ler o arquivo de forma binária"
aStream binary.
"Criamos a imagem como instância de imagem de 8 bits"
imagem := Depth8Image
extent: dimX@dimY
depth: 8
palette: (MappedPalette withColors: cores)
"Lemos o resto do arquivo como pixels"
bits: aStream upToEnd.
aStream close.
imagem inspect.
Exemplo 8.14 Código para ler um bitmap de tonalidades de cinza em formato PGM

174 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 175


Manipulação de arquivos e estruturas de acesso seqüencial

Capítulo 9 0HFDQLVPRGH
'HSHQGrQLFD

Neste capítulo você vai aprender a utilizar os recursos que Small-


talk oferece para permitir que você determine que alguns objetos reajam
de forma automática a alterações sofridas por outros objetos. Isto é imple-
mentado através do mecanismo de dependência e é uma característica
muito peculiar e poderosa de Smalltalk. Nós vamos primeiro explicar os
conceitos associados ao mecanismo de dependência e depois mostrar
como você utiliza e integra este recurso em seus programas.

9.1 Reação Automática a Alterações


O mecanismo de dependência é uma funcionalidade do Smalltalk
que permite que um objeto informe a outros, seus dependentes, quando
sofre uma alteração. Mecanismos de dependência foram pela primeira vez
concebidos para serem usados por estruturas de dados denominadas fra-
mes em aplicações de Inteligência Artificial, no final de década de 70. O
objeto do qual outros são dependentes é conhecido como objeto pai. Os
objetos dependentes são os dependentes. Não existe um número que
limite quantos objetos podem ser dependentes de um objeto pai.

176 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Mecanismo de Dependênica Registrando-se ou Excluindo-se como Dependente

Quando um objeto pai sofre uma alteração, ele envia uma men-
sagem para self (ou seja, ele mesmo) notificando a ocorrência de alguma
alteração em seu estado. Automaticamente, os objetos dependentes são Pai A Pai A Pai B
notificados sobre a alteração no objeto pai e podem tomar as devidas
providências. Não existe a necessidade do objeto pai sabem quais são (dependência) (dependência) (dependência) (dependência)
seus dependentes. Apenas os objetos com interesse especifico em
algum objeto pai, devem se registrar como seus dependentes.
Filho A Filho B Filho A

Pai self changed


Figura 9.2 Dependência de um ou vários pais
adDependent: self (dependência)
ObjetoA addDependent: objetoB.
Quando o objeto B não tem mais interesse em ser dependente
updated
Filho do objeto A, podemos utilizar a mensagem removeDependent: para
executar esta tarefa.
ObjetoA removeDependent: objetoB.
Figura 9.1 funcionamento básico do mecanismo de dependência Caso se deseje remover todos os dependentes de um determi-
nado objeto, podemos utilizar a mensagem release que remove todas
Este tipo de relacionamento entre objetos é útil quando um ou as relações de dependência com seus objetos dependentes. O uso da
mais objetos tem interesse no estado de outro, mas o contrário não é mensagem release é largamente utilizado no VisualWorks para garan-
verdade. É interessante notar que um objeto pode ser dependente de tir que as relações de dependência sejam excluídas quando não se fize-
mais de um objeto Pai. O lado esquerdo da figura 9.2 mostra um objeto rem mais necessárias. A única maneira de um objeto ser excluído da
pai contendo dois dependentes e o lado direito mostra um objeto filho imagem do Smalltalk é quando ele não possui nenhuma referência,
dependente de dois objetos pai. então o garbage collector se encarrega de excluí-lo. Note que não existe
outra maneira de excluir objetos. Então, se a mensagem release não
for enviada para o objeto desnecessário, ele permanecerá na imagem,
9.2 Registrando-se ou Excluindo-se como pois possui dependentes e o garbage collector não o excluirá.
Dependente Então, sempre que uma aplicação criar uma relação de depen-
Para que um objeto B seja dependente de um objeto A ele pri- dência explicitamente, ela também deve sobrecarregar o método rele-
meiro deve se registrar como dependente. A mensagem addDepen- ase e nele se preocupar com a correta exclusão das dependências
dent: se responsabiliza desta tarefa. criadas. Lembre-se de incluir super release para que o método da

178 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 179


Mecanismo de Dependênica Mensagens updated e Mensagens changed

classe Object também seja invocado. Isso garante que todas as depen- protocolo descrição
dências serão corretamente excluídas.
contém mensagens como changed e broad-
Ainda existem outras mensagens que nos fornecem informações changing cast:. Em suma contém as mensagens de
úteis sobre o estado das dependências. Para sabermos quais são notificação
dependentes de um determinado objeto podemos utilizar a mensagem métodos de acesso aos dependentes. Contém
dependents. dependents access mensagens como addDependent: , remove-
ObjetoA dependents. Dependent: e expresInterest:
Essa mensagem retornará um array contendo todos os objetos outros métodos mais avançados referentes ao
dependents collec-
dependentes do objetoA. mecaniso de dependência. São bem pouco
tion
usados
Tabela 9.1 Protocolos dos métodos referentes ao mecanismo de
dependência
9.3 Onde são Definidos os Métodos do Mecanismo
de Dependência? • Métodos do grupo changed.
• Métodos do grupo updated.
O mecanismo de dependência é implementado na classe
Object. Porém ainda existem outras classes que especializam o meca- Cada um dos métodos contigos nos grupos citados acima for-
nismo de dependência. Um exemplo é a classe Model, vista mais adi- nece uma maneira diferente de por para funcionar o mecanismo de
ante. dependência. Variando no grau de informação sobre a alteração. Eles
funcionam em pares.
A base dos métodos está na classe Object. Fica claro que como
todos os objetos, na hierarquia de classe são filhos de Object, qualquer A mensagem changed: recebe como parametro um símbolo.
objeto pode implementar o mecanismo de dependência. Quando ela é invocada, sendo enviada para o próprio objeto pai (self
changed: anAspect), todas os objetos dependentes são notificados
Caso o leitor sentir necessidade de inspecionar os métodos que recebendo a mensagem update: , que recebe como argumento a mesma
implementam o mecanismo de dependência, deve reportar-se a classe variável (anAspect) enviada para a mensagem changed:. No método
Object. tabela 9.1 indica o que cada protocolo desta classe abriga em se update: (objeto dependente), deve ser colocado o código referente a
tratando de métodos relacionados ao mecanismo de dependência. ação esperada perante uma alteração no objeto pai. O aspecto (anAs-
pect) serve como uma informação sobre o motivo da alteração e é defi-
nido pelo objeto pai, podendo ser qualquer símbolo. Caso você não veja
9.4 Mensagens updated e Mensagens changed necessidade de informar para os objetos dependentes o motivo pelo qual
a alteração ocorreu, mande simplesmente a mensagem changed. Ela
Existem dois grupos básicos de mensagens que implementam o
agirá como se você estivesse mandando a mensagem changed: com nil
mecanismo de dependência. São as mensagens que informam a ocor-
como argumento. Em verdade, se o leitor for curioso poderá procurar a
rência de uma alteração no estado da classe pai, métodos changed, e o
implementação da mensagem changed na classe Object, lá veremos
grupo das mensagens acionadas nos objetos dependentes, em decor-
que o que changed faz é chamar o método changed : nil.
rência da alteração do objeto pai, os metodos updated.

180 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 181


Mecanismo de Dependênica Características do mecanismo de dependência

As outras mensagens de changed e updated tem a mesma fun- algumaMensagem é enviada para todos os seus dependentes.
ção apenas tendo um argumento a mais, e no caso da mensagem upda- Também pode ser utilizada a forma:
ted: with: from: o último argumento é o objeto que recebeu a broadcast: #algumaMensagem with: aParameter
mensagem, no caso, a classe pai.
Um problema deste mecanismo é que todas as mensagens de expressInter-
atualização (changed) são enviadas para todos os dependentes. Então estIn: for:
os dependentes precisam implementar uma das mensagens da família sendBack:
de atualização (update) e checar por um símbolo particular que foi envi-
ado.
Isto pode ser eliminado utilizando-se a mensagem expressIn-
terestIn: for: sendBack: ao invés de addDependent: para o
objeto pai. Neste método, é solicitado ao objeto pai para expressar um
interesse em uma mudança particular e enviar uma mensagem especí-
fica quando ele vê o símbolo associado com a mudança. Isto é confuso
porque se poderia esperar que o dependente é quem deveria expressar
interesse pelo objeto pai. Entretanto, a sintaxe é tal que os dependentes
informam ao objeto pai para expressar um interesse pelo dependente.
Para remover o interesse deve ser enviada a mensagem:
pai retractInterestIn: #number for: self

Esta mensagem esconde a complexidade do método expres- onChange-


sInterestIn: for: sendBack:, sendo implementada na classe Send: to:
Figura 9.3 Implementação da mensagem changed
abstrata ValueModel. Recebe dois parâmetros: a mensagem que a ser
enviada e o objeto para o qual a mensagem será enviada. Não é especi-
ficado que mudança é de interesse pelo fato de ValueModel manipular a
9.5 Características do mecanismo de dependência expressão de interesse e a notificação das mensagens. Tudo o que essa
O mecanismo de dependência possui várias características que mensagem faz é expressar um interesse no símbolo #value
diferenciam Smalltalk de outras linguagens. Vam,os aqui analisa-las. ValueModel>>onChangeSend: aSymbol to: anObject
self expressInterestIn: #value
Broadcast Outra facilidade na utilização de dependências é o recurso de
broadcasting, o qual permite uma mensagem ser enviada a cada um dos for: anObject
objetos dependentes. Quando um objeto pai recebe a mensagem: sendBack: aSymbol
broadcast: #algumaMensagem

182 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 183


Mecanismo de Dependênica O mecanismo de dependência e o modelo MVC

Um ValueModel é um wrapper em torno de um valor, ele arma- A classe Model será exaustivamente vista no capítulo que trata
zena o valor. O valor não pode ser diretamente atualizado, isso somente no modelo MVC.
pode ser feito através do ValueModel. Pelo fato do ValueModel ter
esse controle da mudança ele pode notificar os dependentes da altera-
ção. Para alterar o valor deve ser utilizada a mensagem value: com o 9.7 O mecanismo de dependência e o modelo MVC
novo valor como parâmetro.
Certamente o uso mais comum do mecanismo de dependência
ValueModel>>value: newValue
no VisualWorks é observado no modelo MVC (Model-View-Controller,
self setValue: newValue.
visto mais adiante). É sobre o modelo MVC que as aplicações gráficas
self changed: #value são construídas no VisualWorks, e o mecanismo de dependência é utili-
ValueHolder é a subclasse mais simples de ValueModel. zado para manter a comunicação entre as três partes do modelo.

9.6 A Classe Model 9.8 Exercícios


A classe Model é uma classe abstrata e filha direta da classe 1. Navegue pelos protocolos da classe Object citados anteriormente
Object e tem como função implementar uma maneira alternativa para o neste capítulo e verifique a implementação dos métodos que perfazer
mecanismo de dependência. Em verdade, existe um compromisso entre o mecanismo de dependência. Tente também todos os outros proto-
espaço em menória e velocidade de execução. A solução adotada pela colos desta classe e faça uma lista de todos os métodos relacionados
classe Object para implementar o mecanismo de dependência é utilizar com o mecanismo de dependência.
uma variável compartilhada. Já a classe Model utiliza uma variável de 2. Verifique em especial o método breakDependents. Explique porque
instancia para guardar referência de seus filhos. Esta solução tem um ele é defundamental importância para que um método release deja
grande inconveniente, pois quaisquer classes que utilizarem o meca- adequadamente escrito.
nismo de dependência implementado pela classe Object terão seus 3. No método breakDependents outro método é invocado e recebe
filhos registrados na mesma variável de classe. E de se esperar que o como argumento nil. Identifique a quem este outro método faz refe-
rência.
tamanho desta classe cresça em demasia, e pior, se os objetos depen-
dentes não forem corretamente liberados, eles nunca mais sairão de lá, 4. Crie uma classe chamada GeradorDeNumFatoriais que possua um
método que calcule o fatorial de todos os números de 1 a 1000. Em
logo, como o tamanho desta variável só tende a crescer o tempo de con-
seguida crie outra classe chamada ImpressorDeFatImpares que
sulta a ela também cresce.
deverá imprimir no Transcript todos os fatoriais gerados pela classe
Já a solução adotada pela classe Model tem a grande vantágem GeradorDeNumFatoriais que forem impares. Em seguida adicione a
de só agrigar em sua coleção de dependentes aqueles referidos pela ins- classe ImpressorDeFatImpares como dependente de GeradorDeNu-
tancia da classe. Isso não resolve o problema de que se as referências mFatoriais e mande a classe pai executar. A classe filha deverá ser
não forem corretamente liberadas o objeto não seja coletado pelo coletor capaz de mostrar todos os fatoriais impares gerados pela classe pai.
de lixo, mas como a coleção de dependentes é menor, o tempo de pes- Para resolver este exercício, você necessitará criar na classe pai um
quisa também fica menor. método específico para gerar os fatoriais. Pesquise na classe Integer
a mensagem factorial e também tente encontrar onde está definida a

184 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 185


Mecanismo de Dependênica

3URFHVVRVH
mensagem odd. Por fim, utilize o mecanismo de dependência para
resolver este exercício. Capítulo 10
5. A classe Model implementa o mecanismo de dependência de outra
maneira. Qual a vantágem de se implementar o mecanismo de
dependência como a classe Model o faz? 6HPiIRURV

Neste capítulo você vai aprender os mecanismos que Smalltalk


oferece para permitir que vários objetos possuam comportamento e funcio-
nalidades simultâneas de forma independênte dos mecanismos de concor-
rência oferecidos pelo sistema operacional onde Smalltalk está rodando:
os processos internos. Vai aprender também como sincronizar processos
através de semáforos. Por último, você vai aprender que Smalltalk também
permite controlar processos externos em ambientes Unix/Linux onde este
conceito existe, permitindo que Smalltalk controle um programa externo
sendo rodado ao mesmo tempo.

10.1 Processos
Processos são uma maneira de executar e controlar múltiplos pro-
gramas independentes rodando ao mesmo tempo. Seja entendido por pro-
cesso uma aplicação inteira ou apenas parte de um programa.
Tome uma aplicação de tratamento de imagens gráficas como
exemplo de aplicação do conceito de processos. Algoritmos de manipula-
ção de imagens, geralmente demoram segundos ou até mesmo minutos.

186 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Processos e Semáforos Criando e Finalizando um Processo

Ao aplicar um destes algoritmos a uma imagem, um método será invo- versões e na família NT é que esta característica começou a funcionar a
cado para executar a operação. Da maneira tradicional, sem a utilização contento. Os algorítimos por traz do mecanismo de escalonamento de
de processos, seu programa iria ficar executando o algoritmo e outras processos são complexos sendo assunto de cadeiras como sistemas
funcionalidades da sua aplicação ficariam travadas. Se criarmos um pro- operacionais e programação paralela não sendo abordados neste livro.
cesso para executar o algoritmo de tratamento da imagem, ele será exe- Não devemos então confundir processos do Smalltalk, com pro-
cutado em segundo plano deixando sua aplicação livre para perfazer cessos de um sistema operacional.
outras tarefas. Quando o processo terminar, o resultado poderá então ser
apresentado. Sobre sistemas operacionais “preemptivos reais”, como Unix/
Linux , o Smalltalk tem a possibilidade de criar processos do sistema
Funciona- O mecanismo de processos no Smalltalk é o que chamamos de operacional, mas para tal não fazemos uso dos conceitos de processos
mento dos “parcialmente preemptivo”. Isso significa dizer que dois processos não internos ao Smalltalk (utilizando a classe Process), mas sim usamos
processos são executados em paralelo, e sim que eles obedecem certas regras de uma classe específica para funcionar com processos externos sobre tais
prioridade para cadenciar sua execução. sistemas (UnixProcess).

Aqui se faz necessário diferenciar processos dentro de uma ima-


gem Smalltalk e processos do sistema operacional.
10.2 Criando e Finalizando um Processo
Podemos ver processos, em se tratando do mundo Smalltalk,
como tarefas agendadas. Para cada uma das diversas tarefas existe Existem várias formas de se criar um processo em Smalltalk.
uma prioridade que determina a ordem de execução. Então, podemos Talvez a mais simples seja utilizando a mensagem fork. A mensagem
concluir que os processos não são executados em paralelo. Um pro- é definida na classe BlockClosure, e o que ela faz é criar uma instancia
cesso só pode começar quando o processo atual terminar ou receber da classe Process e passar o bloco que recebeu a mensagem como
uma mensagem para parar a sua execução, ou possuir um prioridade parâmetro. Isso leva a criação de um novo processo, com a mesma prio-
maior que o processo que está sendo executado, neste caso o processo ridade do processo que o criou . Este novo processo será agendado em
corrente é parado e o processo de maior prioridade é executado. uma variável global denominada Processor que é a única instancia da
classe ProcessorScheduler e o processo já recebe a mensagem
resume que torna o processo executável. Mais detalhes sobre a classe
Em sistemas operacionais como Unix e Linux, também conheci- ProcessorScheduler serão apresentados posteriormente.
dos como multitarefas ou “preemptivos reais”, processos são tarefas que
são executadas concorrentemente, ou seja, para cada processo existe Podemos criar um processo com seu grau de prioridade já pre- Iniciando um
uma fatia de tempo em que ele poderá executar. Como esta fatia de definido usando a mensagem forkAt:. Como seu funcionamento é processo
tempo é pequena para nossa percepção, temos a impressão de que os análogo ao da mensagem fork apenas alterando sua prioridade deixa-
processos rodam em paralelo. O sistema operacional dedica uma deter- mos ao encargo do leito observar seu funcionamento nos exemplos que
minada parcela do “tempo de máquina” ou “atenção do processador” se seguem.
para executar cada um dos processos do sistema. Em sistemas opera-
.
cionais robustos como o Unix e o Linux, este mecanismo funciona muito
bem já sendo utilizado a décadas, já no Windows somente nas útimas

188 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 189


Processos e Semáforos Criando e Finalizando um Processo

|proc|

proc := [Transcript show: (1000 factorial) / (999 factorial)]


newProcess.

proc resume.
Exemplo 10.2 exemplo de criação de processos através do envio da mensagem newProcces

A mensagem newProcessWithArguments: recebe como


argumento único um array contendo os argumentos que serão passados
para o bloco.
Da mesma forma que podemos agendar um determinado pro-
cesso na variável global Processor, também podemos excluí-lo. Note que
a exclusão de um processo de Processor se dá naturalmente após a exe-
cução do mesmo ser completada, porém em alguns casos, um determi-
Figura 10.1 Implementação da mensagem fork na classe BlockClosure nado processo pode não ser mais necessário, e mantendo-o agendado
em Processor ele fatalmente será executado acarretando desperdício de
|c| recursos do sistema. Outra situação onde é desejável para não dizer
necessário a exclusão de um processo ocorre em casos onde dentro do
c := OrderedCollection new.
processo exista um laço infinito. Como a execução do mesmo nunca
c add: 2; add: 3; add: 4.
chegará ao final, o termino do processo deverá ser forçado.
[c do:[:each| Transcript show: (each printString)]] fork.
Exemplo 10.1 criação de um processo através da mensagem fork A mensagem terminate faz com que um determinado pro-
cesso seja terminado. Note que tal mensagem corta abruptamente a exe-
Como vimos na explicação do funcionamento da mensagem cução do processo que se propõe a finalizar. o exemplo 10.3 mostra o
fork, uma instância da classe Process é criada. Existem ainda muitas funcionamento da referida mensagem.
outras maneiras de se criar um processo.
|p|
Utilizando as mensagems newProcess e newProcessWi-
thArguments: definidas também na classe BlockClosure. A dife- p := Process forBlock: [1 to: 1000 do: [:cont| Transcript show:
rença na criação de processos reside no fato que que o processo recém (cont printString , ' '). (Delay forMilliseconds: 1) wait]]
criado ainda não é executável. Para que ele entre na lista de processos priority: 51.
executável do objeto Processor precisamos enviar a mensagem p resume.
resume para ele (Delay forSeconds: 3) wait.
p terminate.
Exemplo 10.3 Exemplo de uso da mensagem terminate

190 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 191


Processos e Semáforos A Escala de Prioridade

10.3 A Escala de Prioridade


Como foi dito anteriormente, a prioridade de execução dos pro-
cessos dita em que ordem eles serão executados e também e o fator de
decisão para saber se o processo corrente deve ser parado para a exe-
cução de outro.
A prioridade dos processos em Smalltalk é definida por um
inteiro que varia de 1 (menor prioridade) até 100 (maior prioridade).
A classe ProcessorSchedulder é que faz uso da prioridade de
um processo. Ela é responsável por determinar qual processo deve ser
executado em que instante. Existem algumas regras que definem o com-
portamento de decisão sobre que processo executar.
1. Um processo, para ser executado deve estar em estado executável, Figura 10.2 Esquema das principais prioridades pré-definidas
isso é obtido enviando a mensagem resume para ele.
• systemRockBottonPriority representa a menor prioridade pos-
2. Os processos de maior prioridade vem em primeiro plano na fila de sível e é utilizada em processos de pouca importância.
execução.
• systemBackgroundPriority é utilizada para processos do sistema
3. Se um processo está rondando, mas outro de maior prioridade que que devem rodar em segundo plano.
ele é agendado e está no estado executável, o processo atual é posto
• userBackgroundPriority é utilizada para processos criados pelo
em estado de espera (utilizando a mensagem wait) e o novo pro-
usuário que devem rodar em segundo plano.
cesso de maior prioridade é executado.
• userSchedulingPriority é a prioridade padrão. Utilizada pela
Na classe ScheduledProcessor existem algumas mensagens mensagem fork.
organizadas abaixo do protocolo “priority names” que simplesmente • userInterruptPriority prioridade um pouco mais crítica. É utilizada
retornam um inteiro correspondente aos valores de prioridade mais no esquema de gerenciamento de janelas.
comumente utilizados. A utilização destas mensagens deve ser motivada • lowIOPriority prioridade para processos que implementam os
pois se alguma alteração no sistema de prioridades do VisualWorks ocor- dispositivos de entrada e saída não críticos tais como o mouse e
rer em uma versão posterior,como por exemplo a alteração da faixa de teclado
prioridade de 1-100 para 1-1000, com certeza tais mensagens serão atu- • highIOPriority prioridade para processos que implementam os
alizadas para os novos valores padrão e sua aplicação não correrá dispositivos de entrada e saída críticos tais como o HD e dispos-
necessitará ser escrita. A figura 10.2 mostra as mensagens da menor pri- itivos para rede.
oridade para a maior. • timingPriority representa a maior prioridade possível, é utilizada
Cada uma das oito mensagens apresentadas neste esquema é em processos extremamente críticos ou em aplicações em
trempo real.
comumente utilizada dentro do Smalltalk. Sua utilização se dá por uma
referência direta entre seu nome e o propósito a que se destina:

192 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 193


Processos e Semáforos Interrompendo e Forçando a Execução de Processos

A prioridade de um processo pode ser mudada explicitamente método descrição


através do invio da mensagem priority: . PAra sabermos qual a pri-
cria uma instancia da classe Delay onde o argumento é
oridade de um determinado processo podemos utilizar a mensagem forMilliseconds:
assumido em milisegundos
priority.
cria uma instancia da classe Delay onde o argumento é
forSeconds:
assumido em segundos
a partir do momento que for criado esperará o montante de
10.4 A classe Delay milisegundos passado como argumento e então enviará a
untilMilliseconds:
Como o esquema de processos suportado pelo smalltalk não é mensagem wait
preemptivo real, quando um processo tomar o processador ele será exe- Tabela 7.2 métodos para a criação de instancias da classe Delay
cutado até seu termino ou até que um processo de maior prioridade seja
incluido na fila de processos. Para evitar este tipo de problema, o Small- [50 timesRepeat: [Transcript show: '_'. (Delay forMilliseconds: 13)
talk implementa algumns métodos que permitem a suspenção e tentativa wait]] fork.
de execução de processos. Tais métodos serão vistos na próxima seção. [ 50 timesRepeat: [Transcript show: '|'. (Delay forMilliseconds:
13) wait]] fork.
Parando Outra situação muito comum é aquela na qual desejamos que Exemplo 10.4 uttilizando instancias de Delay com processos
momentanea- um determinado processo espere por um determinado montante de
mente a tempo até que ele volte a tomar o processador. Para tais casos existe a
execução de classe Delay . Ela permite que um processo seja paralizado por um 10.5 Interrompendo e Forçando a Execução de
um processo determinado tempo e ao termino do tempo determinado volte a atividade Processos
(claro que respeitando as regras de escalonamento de processos). Ins-
tancias desta classe são particularmente úteis quando estamos traba- Ja discutimos na seção anterior o mecanismo empregado para
lhando com semáforos, que serão abordados mais a frente neste que paremos a execução de um processo durante um determinado
capítulo. Por hora vamos ver como a classe Delay funciona espaço de tempo através do emprego da mensagem wait. Porém
como sabemos, a referida mensagem não tira o processo que a recebe
O método principal desta classe é o wait. Ao ser enviado a da lista de processos esperando pela oportunidade de executar. Nesta
uma instancia de Delay, ele faz com que o processo corrente (o processo seção veremos alguns métodos que nos permitem algumas manipula-
onde a instancia de Delay foi criada) seja paralizado. Para criar instan- ções bem interessantes com processos.
cias da classe Delay existem três métodos de classe. Eles podem ser
vistos na tabela 7.2. Para Tirarmos um processo da lista de processos que estão
esperando para serem executados podemos utilizar a mensagem sus-
Para elucidar o funcionamento de instancias da classe Delay pend. Quando um processo recebe esta mensagem ele para sua execu-
vejamos o exemplo 10.4: ção e é removido da lista de processos esperando. Para que um
processo em estado suspended seja novamente incluido na fila de pro-
cessos a serem executados devemos utilizar a mensagem resume. O

194 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 195


Processos e Semáforos Comunicação entre processos

exemplo 10.5 mostra como um processo pode ser retirado da fila de exe- será suspenso momentaneamente e o bloco passado como argumento
cução. será executado. Ao termino da execução do bloco o processo será nova-
mente retomado.
|p|
|p|
p := Process forBlock: [1 to: 200 do: [:cont| Transcript show:
(cont printString , ' '). (Delay forMilliseconds: 1) wait]] p := Process forBlock: [1 to: 200 do: [:cont| Transcript show:
priority: 50. (cont printString , ' '). (Delay forMilliseconds: 1) wait]]
p resume. priority: 50.
(Delay forMilliseconds: 100) wait. p resume.
p suspend. (Delay forMilliseconds: 100) wait.
[100 timesRepeat: [Transcript show: 'processo 2']] fork. p interruptWith: [100 timesRepeat: [Transcript show: '*']].
p resume. Exemplo 10.7 utilização da mensagem interruptWith:

Exemplo 10.5 utilização da mensagem supend

Como vimos, o primeiro processo é executado até que recebe a


10.6 Comunicação entre processos
mensagem suspend, entao o segundo processo é completamente exe- Processos são utilizados normalmente em duas linhas de
cutado e por fim com o envio da mensagem resume o primeiro pro- emprego. Na primeira o processo é criado e é executado até completar
cesso pode então seguir o seu curso. seu objetivo podendo ser suspenso e retomado obedecendo as regras
Uma segunda mensagem muito interessante é a mensagem de escalonamento vistas anteriormente.
yield. Ela pode tanto ser enviada ao Processor como para o pro- Na segunda, pode surgir a necessidade destes processos se
cesso. No caso de ser enviada ao Processor este se responsabilizará comunicarem, ou seja, trocarem informações. Para suprir esta necessi-
de repassa-la ao processo corrente em execução. Seu funcionamento é dade de comunicação inter-processos, Smalltalk, na sua biblioteca de
muito simples. Quando um processo recebe a mensagem yield ele classes, implementa basicamente duas classes:
parará sua execução e permitirá que outro processo que possua igual
• SharedQueue
prioridade tome vez no processador. Caso não exista nenhum processo
com a mesma proiridade que o processo corrente a menságem yield • Semaphore
não terá efeito. O exemplo 10.6 mostra seu funcionamento. Comunicação entre processos é um assunto que alça as caidei-
ras de Sistemas operacionais e processamento paralelo, porém pode-
[50 timesRepeat: [Transcript show: '\'. Processor yield]] fork. mos afirmar para o leitor que os mecanismos empregados pelo Smalltalk
[50 timesRepeat: [Transcript show: '/'. Processor yield]] fork. para gerenciar esta comunicação, utilizam-se dais mais atuais idéias
Exemplo 10.6 Exemplo de utilização da mensagem yield existentes hoje em dia.
Obviamente, existe vários objetos derivados com características
Outra mensagem que merece destaque é interruptWith: . Ela
especiais para comunicação entre processos, porém podemos entender
espera um bloco como argumento; O processo que recebe a mensagem

196 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 197


Processos e Semáforos Semáforos

o funcionamento básico do mecanismo apenas observando estas duas mativo ele é colocado na fila compartilhada sq. Como o esquema de pro-
classes. cessos em smalltalk não é preenptivo real devemos utilizar a mensagem
yield para dar chance que outros processos também possam ser exe-
cutados. A partir do momento que a mensagem yield é executada o
10.7 Filas Compartilhadas processo 2 se torna ativo ele pede a fila compartinhada pelo seu primeiro
dado, ela retorna o mesmo e ele é impresso. Ao final dacontagem o pro-
Quando desejamos que processos se comuniquem, o primeiro cesso 1 se encarrega de finalizar o processo 2.
passo a ser tomado é a abertura de um canal de comunicação entre eles.
Este canal é aberto instanciando um objeto da classe SharedQueue e |sq p1 p2|
informando os processos a se comunicarem sobre a existência do canal
de comunicação. A classe SharedQueue utiliza semáforos para sincroni- sq := SharedQueue new.
zar a comunicação entre os processos. p1 :=[ 1 to: 100 do:[:cont| (cont odd) ifTrue: [sq nextPut: cont].
O canal de comunicação é normalmente unidirecional, sendo Processor yield ]. p2 terminate] fork.
p2 := [ [true] whileTrue: [Transcript show: (sq next printString),
que um dos processos envia as informações e o outro as recebe.
' ']] fork.
Exemplificando, imagine dois processos Processo1 e Exemplo 10.8 comunicação entre processos atraves de filas compartilhadas
Processo2. Queremos enviar informações do Processo1 para o
Processo2. O primeiro passo é criar uma instancia da classe Shared- Filas compartilhadas também podem ser utilizadas para comuni-
Queue para perfazer a comunicação entre os processos. Em seguida, cação de dados entre vários processos, porém ela não define de maneira
criamos o primeiro processo e utilizamos a mensagem next para espe- alguma prioridades entre os processos para acesso a fila. Simplesmente
rar que o outro processo envie um objeto. Criamos então o segundo pro- qualquer processo pode colocar e retirar dados de uma fila comparti-
cesso que utiliza a mensagem nextPut: que envia o objeto passado nhada.
como parâmetro na mensagem para o primeiro objeto. Note que quando Além dos métodos next e nextPut: existem ainda outros
uma instancia da classe SharedQueue recebe a mensagem next, o métodos muito úteis na classe SharedQueue. Existe por exemplo o
processo corrente fica em estado de espera até que a mensagem nex- método peek que permite que um processo verifique o dado do começo
tPut: seja enviada a partir de outro processo. da fila sem no entanto o retirá-lo de lá. Outro método de extrema impor-
Note que SharedQueue se comporta como uma fila FIFO, sem tância é o size que fornece o número de objetos na fila.
descartando qualquer informação relativa a prioridade dos processos
envolvidos. O primeiro processo a ser agendado como em estado de
espera na instancia de SharedQueue será o primeiro processo que 10.8 Semáforos
receberá um objeto passado para a SharedQueue
A classe Semaphore permite um sinalização sincronizada entre
No exemplo 10.8 vemos a utilização de filas compartilhadas para
processos. Entenda por sincronizada, uma comunicação que não é feita
comunicação entre dois processos. O processo 1 possui um contador
em tempo real, mas sim através de sinais que indicam quando as coisas
que vai de 1 a 100. Durante o processo de contagem, perfaz-se um teste
devem ocorrer.
para verificar se o numero corrente da contagem é impar, em caso afir-

198 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 199


Processos e Semáforos Semáforos

Podemos ver o funcionamento de instâncias da classe Sema- semáforo eles vão entrando no final da fila. O primeiro sinal recebido
phore como uma analogia do funcionamento dos semáforos de transito. libera o primeiro processo em estado de espera. Este processo de fila
Eles sinalizam como o transido deve fluir, e em que sentido, dependendo também é conhecido como FIFO(first in first out), ou seja , o primeiro a
de alguns sinais, tais como sinal verde e sinal vermelho. entrar é o primeiro a sair.
No Smalltalk, semáforos são usados por um processo para sina- É interessante ressaltar que a Classe semáforo não se preocupa
lizar quando outro processo deve continuar. Também são empregados como a prioridade dos processos e sim apenas com a ordem em que
quando um determinado processo deve ficar em estado de espera até eles entraram na fina. Abaixo, um exemplo mostrando a ordem de execu-
que algum recurso seja liberado ou algum evento esperado aconteça. ção dos processos controlados por um semáforo.
Como exemplo imagine uma classe que tivesse como atributo
um nome. Toda vez que este nome fosse alterado, o novo nome deveria
ser mostrado no Transcript. Mas como informar quando o nome foi alte-
rado? É claro que poderíamos, neste caso inserir a linha de atualização F A L T A
do nome no Transcript diretamente no método que altera o nome, mas
digamos que isto não seja possível. Então só nos resta usarmos um
semáforo. Criamos um processo para mostrar o conteúdo do atributo Exemplo 10.10 Ordem de execução
nome e toda vez que ele for alterado, uma mensagem é enviada para o
semáforo avisando que o valor de nome foi alterado e deve ser mostrado O funcionamento básico de semáforos se baseia em 3 mensa-
no Transcript. gens, uma para criar um semáforo, outra para incluir um processo na fila
de espera e finalmente um mensagem para liberaro primeiro processo da
fila.

F A L T A New
Cria um novo semáforo.

Exemplo 10.9 Uma mensagem é enviada a um semáforo Wait


Note que o semáforo não envia nenhuma informação significa- Deve ser enviada ao semáforo dentro do processo
tiva, ela apenas sinaliza. O sentido dado ao sinal é dado pelo programa- que se deseja incluir a fila de espera.
dor.
Toda vez que um processo controlado por um semáforo espera
um sinal ele é agendado em uma fila dentro do semáforo. Se outros pro- Signal
cessos recebem sinal de espera para ficarem esperando por um sinal do Libera o primeiro processo da fila.

200 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 201


Processos e Semáforos Exercícios

para execução? Explique também o funcionamento do agendador de


processos. Procure onde se encontra o agendador de processos e
navegue por sua implementação.
10.9 Criação de processos no UNIX 10. Na sua opinião, em que situações de programação, seria útil utilizar
um processo dentro de suas aplicações. Cite pelo menos cinco situa-
ções.
11. Se o leitor tiver acesso ao sistema operacional Linux ou qualquer
Unix que posui máquina virtual para o visualworks, crie um processo
10.10 Exercícios externo que abra outra instancia de visualworks.
12. Explique detalhadamente o funcionamento dos seguintes métodos:
1. Crie um bloco de código que gere 1.000 números aleatórios entre 1 e
fork
100. Este bloco deve ter ainda duas variáveis de bloco para comtabi-
lizar a quantidade de números impares e pares gerados. Ao final da fork:
contabilização imprima o resultado (valor das variáveis de bloco) no terminate
Transcript. Faza com que o bloco seja executado em forma de pro-
suspendUnconditionally
cesso através do envio da mensagem fork para o mesmo. (Para
gerar números aleatórios utilize a classe Random) wait
4. Repita o exercício acima mas crie o processo como instancia da yield
classe Process. 13. Como vimos neste capítulo, filas compartilhadas são uma maneira
5. Ainda a respeito do exercício 1, almente a quantidade de números simples e um canal seguro para comunicação entre processos.
aleatórios para 100.000.000. Como fariamos para não ficarmos com Porém ela não permite nenhuma forma de controle de acesso base-
nosso ambiente de desenvolvimento parado até o final da execução ado na prioridade dos processos. Proponha e implemente uma sub-
do processo? Forneça alternativas sempre dentro do ambito de pro- classe de SharedQueue que possua esta capacidade.
cessos. 14. Na classe SharedQueue sabemos que os objetos inseridos na fila
6. No exemplo 10.4 criamos uma instancia da classe Delay configurada ficam armazenados em algum tipo de estrutura de dados ou coleção.
para 13 milisegundos. O que aconteceria se almentassemos ou dimi- Verifique que objeto é utilizado como responsável por esta tarefa.
nuissemos este valor? Teste e explique o porque dos resultados obti- Verifique também nesta classe como funciona a sinalização de envio
dos. e retirada de objetos da fila.
7. Qual a diferença em se cirar um processo através do invio da mensá-
gem fork e de criarmos através da menságem newProcess?
Alguma delas exige algum esforço adicional? Caso exisge, explique e
de um exemplo.
8. Quando criamos um processo através do envio da mensagem fork,
com qual prioridade o processo serácriado?
9. Como fazemos para verificar e alterar a prioridade de um processo?
Onde podemos encontrar todos os processos que estão agendados

202 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 203


Processos e Semáforos

Capítulo 11 &DSWXUDH
7UDWDPHQWRGH
([FHo}HV

Neste capítulo você vai aprender o mecanismo empregado pelo


Smalltalk para perfazer o tratamento de erros. Discutiremos a importância
de se tratar adequadamente erros em uma aplicação, os tipos de erros que
podem ocorrer e também diferenciaremos um erro de uma exceção. A
seguir apresentaremos os sinais e exceções-padrão fornecidos pela biblio-
teca de classes. Veremos como eles nos fornecem uma base sólida para
criar nossos próprios sinais e exceções mais específicos, adaptados às
aplicações desenvolvidas visando o usuário final.

11.1 Por Que Tratar Erros ?


A preocupação com a robustez de um programa em um mercado
cada vez mais exigente, que busca minimizar o preço final dos produtos e
maximizar a qualidade, leva-nos inevitavelmente a procurar criar aplica-
ções de software menos suscetíveis a erros.
A maioria das pessoas, principalmente as relacionadas com o
desenvolvimento de software já tiveram algum problema com um pro-
grama que termina abruptamente devido a um erro que executou um ope-

204 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Captura e Tratamento de Exceções Tipos de Erros

ração ilegal. As linguagens de programação de última geração se de acesso a recursos do sistema computacional que podem estar em uti-
preocupam particularmente com este requisito, fornecendo desta forma, lização por outro processo e que requerem acesso exclusivo.
muitas ferramentas para um bom gerenciamento de erros. Como não
poderia deixar de ser, Smalltalk implementa um ótimo mecanismo de Existem outros casos onde uma determinada parcela do pro- Espera à
erros que permite ao programador abstrair muito do código relativo ao grama assume que outra já foi executada. Por exemplo a inicialização de ocorrência de
tratamento de erros e se ocupar quase que exclusivamente com o pro- uma variável de classe. Caso este evento não tenha ocorrido, um erro eventos
blema a ser resolvido programacionalmente. pode vir a ocorrer.
Com a crescente popularização e cotação de importância a
engenharia de software após a crise do software, muita pesquisa foi Erros lógicos por sua vez, são aqueles gerados por uma opera- Erros lógicos
desenvolvida para tornar o software escrito reutilizável, facilitar a manu- ção matemática ilegal como por exemplo uma divisão por zero, ou o no código
tenção, gerenciamento de alterações e uma atenção toda especial foi envio de uma mensagem desconhecida a um objeto.
dedicada para o esquema de deteção e tratamento de erros. Podemos O mecanismo do Smalltalk utiliza a idéia de signals e handles,
ver no decorrer deste livro, que Smalltalk se enquadra muito bem nos onde um sinal é um objeto especializado capaz de tratar um determinado
requisitos mais cotados pela engenharia de software, pois devido a OO tipo de erros.
pura adotada pelo smalltalk, temos a reutilização de código maximizada,
No Smalltalk o mecanismo de exceção é baseado em duas clas-
devido a sua sintaxe simples, as possíveis manutenções em um pro-
ses base: Exception e Signal. A idéia básica por traz do mecanismo é
grama também ficam facilitadas, o gerenciamento de alterações (ou con-
que tando a sinalização de um exceção como a posterior captura do
trole de versões) possui uma ferramenta poderosa no Smalltalk. O ENVY,
mesmo e feita por uma classe do ramo de Signal. A tarefa das classes
facilita em muito este trabalho.
do ramo de Exception é responsável por gerenciar a exceção, ou seja,
Neste capítulo então veremos que o tratamento de erros não foi que ações tomar quando ele ocorrer.
neguigenciado pelo Smalltalk, estando compatível com o utilizado pelas
Este mecanismo embora ainda suportado pelo Smalltalk já se
mais modernas linguagens de programação.
encontra obsoleto sendo mantido unica e exclusivamente por motivos de
compatibilidade, descreveremos o mesmo pois existe a possibilizade do
leitor ter de fazer manutenção em códigos existentes que utilizem o
11.2 Tipos de Erros mecanismo antigo, mas tenha em mente que quando antes o esquema
Podemos dizer que existem basicamente três situações onde de Exceções deve ser mudado para o novo modelo, pois o Cincom não
erros podem acontecer. garante que o suporte a sinais será mantido por muito tempo.
• Recursos indisponíveis No esquema novo tanto a sinalização, a capitura e a informação
• Espera à ocorrência de eventos relativa à exceção ocorrida são responsabilidade de uma classe da hie-
• Erros lógicos no código rarqua de Exception.
Erros são um tipo especial de exceção que pode ocorrer em
Recursos Chamamos de recursos indisponíveis tentativas de abertura de uma aplicação. Uma exceção nada mais é que um fato que desejamos
indisponíveis um arquivo para escrita que já se encontra aberto, ou qualquer outro tipo

206 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 207


Captura e Tratamento de Exceções Mecanismo de Tratamento de Erros

sinalizar. Podemos então dizer que um erro é sempre uma exceção


porém uma exceção nem sempre é um erro.
Existem vários tipos de sinais padrão no Smalltalk, sendo que a
maioria já são suportados diretamente pela classe Object. Na parte de método 1 (contendo tratador)
protocolos de classes da referida classe podemos encontrar o protocolo procura de rotina de
Signal constants que contém métodos que retornam instâncias de obje- método 2 tratamento
tos capazes de tratar vários erros básicos. Mais a frente neste capítulo
veremos como podemos escrever nós mesmos classes para tratar erros método 3
específicos. por hora vamos entender como o mecanismo de tratamento
de erros do smalltalk funciona.
execução método 4

Object método 5 (sinaliza o erro)

GenericException

Exception Figura 11.2 Busca recursiva do erro

Error Na figura 11.2 vemos que o método 1 possui uma rotina de trata-
mento de erros. O código deste método executa o método 2 que por sua
Figura 11.1 Hierarquia de classes reduzida das exceções
vez executa o método 3 que por sua vez executa o método 4. Durante a
execução do método 4 um erro ocorre. Como não existe nenhuma rotina
de tratamento de erros no método 4 o erro sinalizado neste método per-
corre a pilha de execução do método 4 para o método 1 onde encontra
11.3 Mecanismo de Tratamento de Erros um sinal capaz de trata-lo. Teoricamente, este mecanismo pode parecem
O interessante do mecanismo de tratamento de erros adotado um tanto quanto abstrato. Caso o leitor não esteja certo de ter entendido,
pelo Smalltalk é que se assume de antemão que tudo que o programador reportece ao exemplo 11.1.
programou vai funcionar. Mas como nada é perfeito, dificilmente esta Este é um exemplo completo onde criamos uma classe que
situação ideal irá ocorrer. Ai entra o mecanismo de tratamento de erros, representa o clock de um computador. Ela tem hertz como variável de
ele fica a escuta de sinalizações de erros. Quando algum é encontrado instancia que é a abstração da velocidade do clock. No método initialize
ele o trata. incluímos a rotina de tratamento de erros. Ela consiste na criação de um
Desta forma não precisamos incluir código de tratamento de sinal que no caso utilizamos um sinal genérico definido na classe Object
erros para cada método, basta que algum método na pilha de execução (mais sobre este sinal a frente). De posse da instância do sinal utilizamos
seja capaz de trata-lo. A figura 11.2 mostra como funciona a busca recur- a mensagem handle: do: que espera como argumentos dois blocos.
siva pela pilha de execução. No primeiro vai a rotina que deve ser executada caso algum erro ocorra.

208 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 209


Captura e Tratamento de Exceções Sinais

Já na segunda vai o código do método propriamente dito. Este esquema "TEMPLATE PARA CRIAÇÃO DA CLASSE"
se refere ao mecanismo antigo onde utilizavamos sinais para tratar os Smalltalk defineClass: #NameOfClass
erros ocorridos. No novo modelo devemos criar uma instancia de uma superclass: #{NameOfSuperclass}
das classes da hierarquia de Exception e enviarmos a mensagem on: indexedType: #none
do: para ela. private: false
instanceVariableNames: 'instVarName1 instVarName2'
Para testarmos nosso exemplo podemos avaliar a seguinte
classInstanceVariableNames: ''
expressão no workspace:
imports: ''
Clock new: 10. category: 'Exemplos'
O que acontecerá? Como inicializamos a variável hertz com 0 "MÉTODOS DE CLASSE"
quando tentarmos dividir 1 por ela, um erro será sinalizado pois tentamos new: hertz
|inst|
dividir um número por zero. Como no método período não existe
inst := super new initialize.
nenhuma rotina de tratamento de erros, o sinal percorrerá o caminho
inst hertz: hertz.
oposto a pilha de execução passando então para o método initialize ^inst.
que foi o método que invocou período. Veremos mais exemplos a "MÉTODOS DE INSTANCIA"
frente neste capítulo, então caso o leitor não entenda o exemplo em sua initialize
plenitudo, não se desespere. (Object errorSignal)
Como este método possui uma rotina de tratamento de erros o handle:[:ex|
erro sinalizado no método periodo será tratado sendo então executado Dialog warn: (ex errorString).
]
o bloco passado como parametro para a palavra-chave handle.
do: [
hertz := 0.
Transcript show: (self periodo printString).
11.4 Sinais ].
hertz
Como dissemos anteriormente sinais são um recurso obsoleto e ^hertz
que apenas é mantido na biblioteca de classes por um motivo de compa- hertz: novaFrequencia
tibilidade. Um sinal trabalha em cooperação com uma exceção para pro- hertz := novaFrequencia
ver uma resposta particular para um tipo específico de erro. Por exemplo, periodo
um sinal deve ser desenvolvido para perceber um erro de uma divisão
por zero. ^1 / hertz.
Na verdade, a classe ArithmeticValue é definida como um sinal. Exemplo 11.1 Tratamento do erro divisão por zero

Cada sinal é normalmente criado por uma classe que se preo- classe DivisionByZero é acessível pelo método divisionByZero.
cupa com um tipo específico de erro. Claro que estamos falando de clas- Este esquema possibilita que aplicações acessem qualquer sinal que
ses especializadas da hierarquia de classes dos sinais. Por exemplo, a

210 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 211


Captura e Tratamento de Exceções Exception e exceções do sistema

esta atualmente definido na biblioteca de classes, e também provê uma


maneira conveniente de identificar pelnamente qualquer sinal.
Cada novo sinal criado é filho de um sinal pré-existente. A
maneira mais simples de se criar um sinal é enviando a menságem new-
Signal para uma das subclasses de Signal. O pai pode então perceber
suas próprias exceções bem como a de seus filhos. Isso pode parecer
um tanto quanto confuso pois esta característica é exatamente contrária
a OO que, como sabemos dita que uma subclasse conheça o comporta-
mento de seus ancestrais. Podemos justificar esta característica se pen-
sarmos que uma classe filha de um sinal refina o tatamento de um erro
mais específico, podendo este ainda ser tratado de uma maneira gené-
rica por uma classe pai. Vejamos um exemplo. Se observarmos a figura
11.1 , vemos que Error é uma especialização de Exception. Desta
forma, qualquer erro que a classe Error pode genenciar a classe Excep-
tion também o poderá pois como dissemos anteriormente neste capítulo,
todo erro é um tipo de exceção.
Figura 11.3 Janela de tratamento de exceções padrão do VisualWorks
A classe Object possui a facilidade de tratar erros. Desta forma
a biblioteca de classes garante-nos que nenhum erro ocorrido durante a sível traduza o esquema de tratamento de erros antigo para o novo
execução de um programa ficara sem ser tratado, pois como sabemos, esquema baseado em exceções que será apresentado mais a frente.
todas as classes em Smalltalk são filhas de Object. Porém o tratador
padrão do Smalltalk não é de maneira alguma conveniente para uma
aplicação comercial, pois como vemos na figura 11.3 , ele nos abre uma 11.5 Exception e exceções do sistema
janela indicando a exceção ocorrida e nos permite debugarmos a aplica-
ção, procedermos com a execução do programa, terminar o programa ou Agora falemos do novo mecanismo. Primeiramente apresentare-
copiar a pihla de execução para a área de transferência. Em aplicações mos algumas das classes da hierarquia de exceções em seguida mostra-
profissionais, não gostariamos que esta janela aparecesse. neste ponto remos o novo mecanismo de tratamento e por fim veremos como
surge a necessidade de criarmos nossos próprios sinais para capiturar podemos criar nossas próprias exceções.
estes erros antes que eles sejam capiturados pelo sinal padrão do Small- Exceções ou erros são representados como objetos ,obede-
talk. cendo a hierarquia de classes apresentada anteriormente . Existem
Vale lembrar mais uma vez que apresentamos o esquema de várias subclasses que especializam diverços tipos de erros. A tabela 11.1
sinais unica e exclusivamente para que o leitor tome ciência de que este mostra algumas destas classes mais comuns. Todas estas classes mais
mecanismo existe. Mas o leitor não deve de maneira nenhuma utiliza-lo. especializadas tratam diversos tipos de erros e podem ser utilizadas
Durante as possíveis tarefas de manutenção de código, sempre que pos- livremente pelos programas dos usuários. É importante ressaltar que

212 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 213


Captura e Tratamento de Exceções Capiturando exceções

estes são sinais padrão que devemos utilizar como base para criar nos- |a b|
sos próprios sinais como veremos nas próximas seções. a := 10.
b := 0.
classe evento [a / b]
ArithmeticError erro ao avaliar uma expressão matemática on: GenericException
do: [:ex| Dialog warn: 'ocorreu um erro'].
Error Qualquer erro em um programa
Exemplo 11.2 Outra forma de capiturar exceções
MessageNotUnderstood Uma mensagem é enviada a umobjeto que não imple-
menta um método correspondente Ao executar o código do exemplo 11.2 veremos a janela apre-
Notification Um evento inusual mas que não impede a execução do sentada na figura 11.4 . Como podemos ver nenhuma janela de Exceção
programa padrão foi aberta e esta, é sem dúvida uma maneira muito mais profissio-
Warning Um evento incomum que o usuário deve ser informado nal de apresentação de exceções em um aplicativo final.
sobre.
ZeroDivide Quando se tenta dividir um numero por zero
Tabela 11.1 mais comuns subclasse de Exception

11.6 Capiturando exceções


Nesta seção veremos como podemos utilizar as exceções Figura 11.4 execução do exemplo 11.2
padrão para tratar alguns erros. Anteriormente no exemplo 11.1, mostra-
mos como podemos capiturar uma exceção sinalizada por classes da Para o exemplo 11.2 utilizamos uma exceção muito genérica
biblioteca padrão (No modelo antigo). Nesta seção mostraremos mais para tratar a divisão por zero ocorrida. Porém poremos utilizar ainda
exemplos utilizando outros métodos para perfazer o mesmo trabalho e outras exceções mais especializadas. O exemplo 11.3 mostra ainda
na seção seguinte apresentaremos como podemos nós mesmos sinali- outra maneira de capiturarmos a mesma exceção. Como poderemos
zar a ocorrência de uma exceção. observar mesmo a classe mais genérica pode identificar quem sinalizou
o erro.
A maneira atual do novo mecanismo de se tratar exceções é
enviando a mensagem on:do: para um bloco. Este método espera Vale a pena o leitor executar o código do exemplo 11.3 no works-
como parâmetros uma classe da hierarqua de exceções e um bloco a ser pace e verificar que todos são equivalentes gerando exatamente o
executado em caso de alguma exceção ser capiturada pelo sinal, respec- mesmo resultado.
tivamente. Note que o segundo bloco espera um argumento, este será Então tenhamos em mente que a forma básica de se capiturar
uma instancia de uma das classes tipo exceção que foi sinalizada exceções em Smalltalk é:
durante a tentativa de se executar a divisão por zero.
[... Código ... ]
on: <Lista de exceções separadas por ,>

214 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 215


Captura e Tratamento de Exceções Sinalizando exceções

"utilizando a exceção Exception" do:[:ex| ... código de tratamento...]


Devemos resaltar que a janela de exceção nos fornece grande
|a b| facilidade em tempo de desenvolvimento para depurarmos e refinarmos
a := 10. nossos programas. Mas veja bem, apenas em tempo de desenvolvi-
b := 0. mento.
[a / b]
on: Exception
do: [:ex| |msg |
msg := 'Ocorreu um erro' , ' (',ex messageText , ') '. 11.7 Sinalizando exceções
msg := msg , ' , ' , (ex originator) printString.
A maioria das exceções que um aplicativo necessita tratar já se
Dialog warn: msg.
encontra implementada na biblioteca de classes. Porém pode ser que
].|a b|
"Utilizando a exceção ArithmeticError" durante o processo de desenvolvimento de aplicações necessitemos tra-
|a b| tar exceções mais específicas, ou seja, exceções geradas pela aplicação
a := 10. para algum tipo de sinalização qualquer. Para estes casos, a parte da
b := 0. hierarquia de classes relativa ao tratamento de exceções possibilita que
[a / b] explicitamente sinalizemos que uma exceção ocorreu. Para perfazer tal
on: ArithmeticError tarefa podemos utilizar o método raizeSignal.
do: [:ex| |msg |
Se um tratador de exceções foi especificamente escrito para
msg := 'Ocorreu um erro' , ' (',ex messageText , ') '.
capiturar a exceção sinalizada, como vimos na seção anterior, ele a tra-
msg := msg , ' , ' , (ex originator) printString.
Dialog warn: msg. tará, de outra forma, esta exceção será invariavelmente capiturada e tra-
].|a b| tada pelo tratador padrão encontrado na classe Object.
A mensagem raizeSignal simplesmente indica que uma
"utilizando a Exceção ZeroDivide" exceção ocorreu, criando uma instancia da exceção relativa a instancia
|a b| da hierarquia de exceções que a sinalizou. Podemos também utilizar a
a := 10. mensagem raizeSignal:, que espera uma string como parâmetro e
b := 0.
representa a descrição da exceção ocorrida. A tabela 11.2 apresenta
[a / b]
alguns dos métodos mais comumente utilizados para o tratamento de
on: ZeroDivide
do: [:ex| |msg | exceções.
msg := 'Ocorreu um erro' , ' (',ex messageText , ') '.
msg := msg , ' , ' , (ex originator) printString. [Error raiseSignal]
Dialog warn: msg. on: Error
].|a b| do: [:exception |
Dialog warn: 'Ocorreu uma exceção']
Exemplo 11.3 outras formas de tratar a mesma exceção Exemplo 11.4 Sinalizando uma exceção explicitamente

216 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 217


Captura e Tratamento de Exceções Ações pós-ocorrência de uma exceção

A menságem raiseSignal embora sinalize de maneira correta [10 / 2]


a ocorrência de uma exceção, nos permite pouco controle sobre a infor- on: ZeroDivide, Warning
mação que será passada pela exceção. podemos então utilizar uma de do: [:ex| Dialog warn: ’Algum erro!’]
suas variantes, a mensagem raiseSignal:.Esta mensagem nos per- Exemplo 11.6 Gerenciamento de multiplos erros
mite passar uma string como parâmetro que será então retornada pela
exceção. O exemplo 11.5mostra como podemos reescrever o código
anterior utilizando esta mensagem. 11.8 Ações pós-ocorrência de uma exceção
[Error raiseSignal:'Ocorreu uma exceção' ] Quando desejamos que o tratador de exceções retorne algum
on: Error objeto após a exceção ser devidamente tratada, devemos obedecer as
do: [:ex | regras de funcionamento de blocos, ou seja, se colocarmos o objeto que
Dialog warn: ex errorString] se deseja que seja retornado na última linha do bloco, ele será retornado
Exemplo 11.5 Equivalente ao exemplo 11.4 a quem recebeu a mensagem que continha o tratador de erros.

No exemplo 11.5, podemos observar que a instancia de uma método ação


exceção que é esperada como argumento pelo bloco tratador de exce-
exit ou exit: Termina método
ções possui muitas outras informações que podemos utilizar. Para uma
maior compreenção de todas as informações contidas em uma exceção Retorna da mensagem que sinalizou a exceção con-
resume ou resume:
inspecione-as. tinuando normalmente a execução do programa
Retorna nil do bloco de código onde ocorreu a exce-
retorn ou return:
Método Responsabilidade ção
raise sinaliza a ocorrência de uma exceção retry Reavalia o bloco de código
raiseSignal Abandona o tratador de exceções e executa o bloco
retryUsing:
passando como argumento para esta memsagem
raiseSignal:
Sinaliza um outro sinal no lugar do recebedor da
notifierString: resignalAs:
mensagem
errorString pass Avalia a ação no bloco de exceções e depois sai.
errorStringExtra: Tabela 11.3 Ações pós-ocorrência de uma exceção
Tabela 11.2 Métodos comumente utilizados
Para que nosso tratador seja capaz de capiturar multiplos tipos
de erros podemos coloca-los todos separados por virgulas como argu- 11.9 Criando seus próprios tratadores
mento para a palavra chave on:. O exemplo 11.6 mostra como podemos
Muitas exceções podem ser sinalizadas e devidamente capitura-
perfazer esta tarefa.
das por classes pré-existentes na biblioteca de classes. Exceções como

218 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 219


Captura e Tratamento de Exceções Exercícios

divisão por zero, mensagem desconhecida earquivos inacessíveis, são Uma outra abordagem é criar uma heirarquia de classes, uma
todas préviamente suportadas. subclasse da outra e por sua vez a de mais alto nível subclasse de uma
Caso não escrevamos uma rotina para tratar esters possíveis das classes da hierarqua de Signal. Como sabemos que uma classe pai
erros, em última instância a classe Object as capturará e tratará utili- possui a capacida de capiturar as exceções que suas classes filhas
zando o tratador padrão citado anteriormente neste capítulo. Como esta gerenciam, usamos a classe de mais alto nível para executar esta tarefa.
solução não é nem um pouco profissional, devemos criar nossos próprios
sinais para gerenciar de maneira adequada nossas exceções.
11.10 Exercícios
A maneira mais simples de se criar um sinal é enviando a men-
sagem errorSignal para a classe Object. Ela por sua vez, retronará 1. Procure a classe Exception no System Browser e selecione a obção
uma instância da classe Error, que como pdemos ver na hierarqua de Spawn hierarchy. De posse do browser de classes expandidas, dese-
classes simplificada mostrada na figura 11.1 , é subclasse deGenericer- nhe a árvore de classes das exceções.
ror. 2. Citamos neste capítulo que existem diverças maneiras de se obter
uma instancia da classe Error. Procure a implementação das manei-
Como sabemos, Smalltalk é uma linguagem extremamente ver-
ras apresentadas e verifique que em suma todas são realmente
sátil, desta forma existem várias maneiras de fazer a mesma coisa. O
equevalentes.Justifique.
exemplo 11.7 mostra maneiras equivalentes para perfazer a mesma
3. Na classe clock apresentada neste capítulo, crie um sinal para sinali-
tarefa cumprida pelo comando Object errorSignal.
zar quando a freqüência exceder o valor de 100MHz. Abra uma
janela de aviso para indicar ao usuário a exceção ocorrida.
Object errorSignal newSignal 4. O seguinte fragmento de código se utiliza o esquema antigo de trata-
Signal new mento de erros. Como possivelmente ocorrerá durante processos
Exemplo 11.7 maneiras alternativas de se cirar uma instancia padrão de Error onde haja a necessidade de fazer manutenção em códigos pré-exis-
tentes, traduza-o para o novo esquema de tratamento de erros.
Podemos organizar nosso mecanismo de tratamento de diver-
|cont|
ças formas. A mais simples é utilizar apenas um sinal para tratar todos os
erros ocorridos em uma aplicação. A segunda abordagem é utilizar (Object errorSignal)
vários sinais, um específico para cada tipo de exceção ocorridae por fim handle:[:ex| Dialog warn: 'Erro!!!!']
utilizar uma coleção de sinais. do:[cont := 0.
Como dissemos anteriormente, podemos utilizar apenas um Transcript show: cont ].
isnal para tratar todos os erros de uma aplicação. Podemos então utilizar Identifique também qual a causa do erro e corrija-o se possível.
um sinal genérico para todas as exceções. Esta abordagem funciona
muito bem para pequenas aplicações porém fornece muito pouco con-
trole sobre os diverços tipos de exceções que possivelmente poderão
ocorrer.

220 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 221


Captura e Tratamento de Exceções

Capítulo 12 6XSHUItFLHVJUiILFDV
FRQWH[WRJUiILFRH
SULPLWLYDVJUiILFDV

Neste capítulo você vai aprender quais são os widgets, compo-


nentes gráficos, implementados por VisualWorks e como utilizá-los para
construir programaticamente interfaces gráficas de usuário. Você também
vai aprender como utilizar as primitivas geométricas do Smalltalk, como
pontos, linhas e curvas e quais são suas propriedades. Veremos também
como manipular imagens sejam elas criadas a partir de listas de bits ou
abertas de um arquivo pré-existente.Por último, você vai aprender a criar e
usar bitmaps, imagens, ícones e cursores Ao final deste capítulo o leitor
estará capacitado a trabalhar amplamente com o framework gráfico forne-
cido pelo VisualWorks.

12.1 Objetos Gráficos em VisualWorks


VisualWorks possui uma vasta gama de classes para manipula-
ção de imagens e objetos gráficos organizados em forma de um fra-
mework. Boa parte das idéias para manipulação de informação gráfica
desenvolvida dentro do projeto Smalltalk são hoje em dia amplamente
difundidas e utilizadas em várias outras ferramentas de desenvolvimento.

222 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Superfícies gráficas, contexto gráfico e primitivas gráficas Superfícies Gráficas

Este capítulo tem por objetivo apresentar ao leitor o mecanismo série de primitivas para a converção da informação gráfica em diretivas
de funcionamento deste rico framework. Abordademos inicialmente o do sistema gerenciador de janelas utilizado pela plataforma.
conceito de superfícies gráficas explicando sua função. Em seguida Em geral instâncias da classe DisplaySurface raramente serão
apresentaremos alguns dos objetos gráficos suportados pelo framework, úteis, mas vale a pena dar uma olhada na implementação desta classe, o
construindo alguns exemplos para elucidar os conceitos. Dentre os obje- conhecimento de sua funcionalidade pode facilitar em muito tarefas mais
tos apresentados estão textos, figuras, linhas, polígonos, icones e curso- avançadas em manipulação de informação gráfica.
res. Esta parte da biblioteca de classes, é onde as diversas
implementações de Smalltalk diferem. Como nós escolhemos Visu- Seja qual for a superfície gráfica em questão, elas sempre
alWorks como implementação Smalltalk de referência para este livro, necessitarão de uma instância da classe GraphicsContext como inter-
muitos dos exemplos que nós vamos prover neste capítulo não vão funci- mediária para a apresentação de qualquer objeto gráfico. A classe Gra-
onar totalmente sem problemas em Visual-Age ou Squeak. phicsContext gerencia alguns parâmetros gráficos tais como espessura
de linhas e será vista em detalhes mais a frente neste capítulo. Mesmo
Executando Os exemplos providos neste capítulo dependem para fun-cionar para impressão, você necessita de um contexto gráfico: Smalltalk imple-
os exemplos de você ter carrregado o parcel ExamplesBrowser que vem com a dis- menta uma classe chamada PostScriptGraphicsContext1 para a gera-
deste capí- tribuição padrão de VisualWorks. Usamos o método prepareS- ção de arquivos em formato .ps, que podem ser enviados a impressoras
tulo cratchWindow da classe ExamplesBrowser para abrir uma janela laser para impressão ou usados para gerar documentos PDF. Na pró-
simples onde vamos desenhar. Incluir código para abrir uma janela no xima seção vamos examinar o contexto gráfico padrão em detalhes.
exemplos os tornaria demasiado longos e desviaria a atenção do que
queremos mostrar. O código deste método é bastante simples e você Instâncias da classe GraphicsContext e suas subclasses ser- Contexto
pode dar uma olhada nele e entender facilmente o que ele faz. vem como um intermediárias entre a superfície gráfica e os objetos gráfi- gráfico
cos por ela mostrados. Esta classe se responsabiliza por vários outros
parâmetros gráficos como por exemplo a espessura das linhas, a fonte
padrão a ser utilizada pelos textos gráficos ou a cor padrão.
12.2 Superfícies Gráficas
Nenhum objeto gráfico é diretamente apresentado em uma
Para que qualquer informação gráfica seja apresentada na tela superfície gráfica. Tudo o que se quiser apresentar deve ser repassado
ela deve ser direcionada para uma “superfície de apresentação”. Existem para o contexto gráfico. Existem vários métodos para apresentação de
três tipos de superfícies de apresentação no VisualWorks. Elas estão lis- objetos específicos ou para a apresentação genérica de um objeto supor-
tadas a seguir: tados por uma instância de GraphicsContext. O contexto gráfico tam-
• Janelas bém suporta mensagens para a alteração de parâmetros gráficos.
• Pixmaps ou matrizes de pixels
Como a apresentação de vários objetos gráficos pode alterar
• Máscaras repetitivamente os parâmetros do contexto gráfico, cada operação é res-
Elas são representadas pelas classes Window, Pixmap e ponsável por ajustar seus parâmetros.
Masks respectivamente. Todas elas são subclasses de DisplaySurface.
Esta classe interage diretamente com a máquina virtual, e suporta uma
1. Em um parcel denominado PostScriptPrinting

224 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 225


Superfícies gráficas, contexto gráfico e primitivas gráficas Superfícies Gráficas

A classe GraphicsContext é uma superclasse abstrata de A classe Pixmap é uma superfície gráfica que tem como princi- Pixmaps
outras duas classes de nosso interesse. Dizemos que existem dois tipos pal característica não ser mostrada na tela diretamente, mas sim ter suas
de contextos gráficos. Os contextos gráficos que apresentam objetos na operações gráficas feitas em segundo plano, tendo que ser mostrada em
tela e os contextos gráficos que geram código PostScript para que seja outra superfície gráfica, ou seja uma janela. A vantagem de perfazer ope-
impresso As classes que implementam estes dois tipos de contextos rações gráficas em segundo plano reside no fato de certas operações
gráficos são ScreenGraphicsContext e PostScriptGraphicsContext são muito complicadas ou a imagem a ser mostrada ser muito grande.
respectivamente. A classe GraphicsContext também possui funcionalida- Este tipo de operação pode demorar muito tempo, então a utilização de
des para redimencionar os objetos por ela mostrados, definir janelas de uma instância de Pixmap para executar a operação e depois apenas
visibilidade (clipping e viewport). transferir o resultado para uma janela se torna uma tarefa bem rápida. O
Instanicas de GraphicsContext não podem ser criadas a ermo, resultado das operações executadas em uma instância de Pixmap
elas em geral são capturadas de uma janela (pois a janela, como vere- podem ser apresentados utilizando a mensagem displayOn:at:
mos a frente é a única saída gráfica existente) e então, possuindo uma Uma instância de Pixmap pode ser criada por exemplo contendo o con-
referência para esse tipo de objeto podemos apresentar nossas informa- teúdo da área de transferência utilizando para isso a mensagem
ções gráficas. fromClipboard, ou diretamente vazia.

A título de exemplo deste livro utilizaremos o contexto gráfico da Note que instâncias da classe Pixmap dependem de recursos
janela de exemplos do help a semelhança de como é feito nos exemplos do sistema operacional, logo uma imagem armazenada em uma de suas
fornecidos pelo VisualWorks para não confundir a cabeça do leitor, mas a instâncias será perdida ao sair do sistema. Para corrigir este problema
frente no livro apresentaremos como capturar o contexto gráfico de qual- utilizamos instâncias da classe CachedImage.
quer janela. A captura do contexto gráfico da janela de exemplos do relp
do VisualWorks pode ser capturada como apresentado no exemplo A classe Mask é outra superfície gráfica onde se pode definir Máscaras
12.1.Como toda operação gráfica pode potencialmente alterar o contexto regiões geométricas dentro de uma área retangular. As máscaras con-
gráfico de um superfície gráfica, não devemos nunca armazenar um con- tém um array bidimencional, uma matriz, onde cada célula corresponde a
texto gráficos em uma variável de instanica ou de classe, mas para efeito um pixel desta área retangular. Cada pixel tem associado um valor alpha
de manipulação local do contexto gráfico dentro de um método podemos que varia entre 0 e 1 e representa o grau de cobertura. Os valores supor-
referencia-lo por uma variável temporária, como podemos ver no exem- tados são 1 (completamente coberto) e 0 (completamente descobertos).
plo 12.1. Note queeste exemplo só funcionará se o help houver sido car- Máscaras são utilizadas para definir regiões de trasparência e também
regado. para sobrepor imagens.

| gc | Uma janela é uma superfície gráfica que é agendada pelo geren- Janelas
gc := (Examples.ExamplesBrowser prepareScratchWindow) ciador de janela de sua máquina. Se desenvolvermos uma aplicação no
graphicsContext. VisualWorks utilizando o Windows e depois abrirmos a mesma imagem
Exemplo 12.1 capiturando o contexto gráfico no Linux, ela funcionará da mesma maneira mais a aparência da aplica-
ção se adequará as características do sistema operacional. Essa carac-
terística pode ser observada na figura 12.3 abaixo. As janelas recebem
eventos e são a superfície gráfica mais comumente utilizada.

226 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 227


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

ção ScheduledControllers (ShceduledControllers é uma variável global


instância única da classe ControlManager que tem uma referência a
todos os controllers das janelas agendadas) para que ela possa receber
o controle de entrada.
A classe ScheduledWindow por si só não é muito útil, pois
embora possua todas as funcionalidades do sistema, ela não provê
mecanismos para criação de aplicações. Em contrapartida ela possui
Falta Janela no KDE uma subclasse, a classe ApplicationWindow que soluciona tal deficiên-
cia. Esta classe possui um grande relacionamento com a classe Applica-
tionModel que é a classe usada para criação de aplicações. A classe
ApplicationWindow ainda possui a capacidade de possuir janelas filhas
para as quais consegue repassar eventos. Uma vez que a janela pai for
fechada todas as filhas também o serão. Uma instância da classe Appli-
cationWindow é criada da mesma forma que uma instância de Schedu-
ledWindow.

| win |
Figura 12.3 Exemplo de uma mesma janela no Windows e no Linux sob KDE
win := ScheduledWindow new.
win minimumSize: (size := 500 @ 300).
A classe Window possui algumas subclasses que apresentam
win open
características específicas o que faz com que uma instância da classe
Exemplo 12.2 criando uma janela em branco
Window dificilmente seja criada. A classe ScheduledWindow é uma
das especializações da classe Window e possui em adição as funciona-
lidades como controlar seu tamanho máximo e mínimo. Ela também pos-
sui um controller (controllers fazer parte do paradigma MVC e serão 12.3 Objetos Gráficos
vistos em um capítulo específico) que fornece um menu com todas as A maioria dos objetos gráficos aqui apresentados se encontram
operações padrão de uma janela e possui um componente visual que organizados sob o protocolo Graphics-Geometry. Eles fazem parte do
serve para que componentes gráficos possam ser adicionados a classe. framework gráfico do VisualWorks e são de fácil manipulação. Nas sub-
Note que apenas um componente gráfico pode ser adicionado a uma ins- seções seguintes seguiremos o seguinte padrão: apresentaremos cada
tância da classe ScheduledWindow. um dos objetos gráficos explicando detalhes tais como métodos para cri-
Uma instância da classe ScheduledWindow é criada utilizando ação, alteração de atributos e apresentação em um contexto gráfico. Em
as mensagens new ou model:label:minimumSize:. Caso se seguida apresentaremos alguns exemplos para elucidar a teoria estu-
deseje alterar alguns atributos gráficos como o label, o ícone etc, existem dada.
mensagens apropriadas, ela pode ser aberta utilizando a mensagem Todo o framework para apresentação de objetos gráficos no
open ou openIn: que se responsabilizam por agendar a janela a cole- VisualWorks foi projetado para apresentar informação gráfica em duas

228 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 229


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

dimensões. Existem alguns esforços no sentido de manipular informa- apresentar nossos textos na tela. O exemplo 12.4 na página 233 mostra
ções gráficas em três dimensões, como é o caso do projeto sun que é como podemos fazer isso.
brevemente discutido ao final deste capítulo. Mais informações poderão
ser encontradas na referência bibliográfica ao final deste capítulo. "exemplo de utilização da classe Text"
|text gc|
Textos Textos são para o VisualWorks tratados como objetos gráficos gc := (Examples.ExamplesBrowser
em muitos contextos e podem ser perfeitamente apresentados em qual- prepareScratchWindow) graphicsContext.
quer contexto gráfico. Particularmente instâncias da classe Text e Com-
posedText são de maior interesse no contexto gráfico. Elas provem text := Core.Text string: 'Smalltalk Completo'
características de formatação adicionais as encontradas na classe emphasis: #(#bold #large).
String. Porém instâncias da classe String podem ser convertidas para text displayOn: gc at: 10@40.
instâncias da classe Text enviando a mensagem ‘asText’. text := Core.Text string: 'Smalltalk é 100% OO'
emphasis: #italic.
Instancias da classe Text podem ter sua aparência mudada de text displayOn: gc at: 10@55.
diverças formas. Para criar um texto por exemplo em negrito poderíamos Exemplo 12.3 Desenhando texto formatado em um contexto gráfico
enviar a mensagem ‘emphasis:’ passando como argumento o símbolo
#bold. A tabela 12.3 sumariza todos os tipos de mudanças suportadas Porém também podemos apresentar instâncias da classe
pela classe Text: String. Para isso utilizamos a mensagem ‘displayString: at:’. esta men-
sagem espera como parâmetros uma string e o ponto de ínicio para apre-
#bold #italic sentação. O melhor de tudo é que mesmo instâncias da classe String
#serif #small podem ter sua aparência alterada, pois instâncias de GraphicsContext
implementam tratamento do tipo e estilo de fonte.
#underline #strickeOut
#sansSerif #large Note que é sempre melhor utilizar instâncias da classe Text pois
como sabemos qualquer operação gráfica pode alterar os atributos do
Tabela 12.3 Estilos de texto
contexto gráfico não garantindo desta forma que no momento da apre-
Em casos onde desejamos alterar a aparência de um texto em sentação de strings os parâmetros estejam corretamente definidos. Exis-
mais de um aspecto tmabém podemos utilizar a mensagem ‘emphasis:’ tem outras mensagens úteis definidas na classe Text que sumarizamos
porém passando como argumento um array contendo os símbolos relati- na tabela 12.4.
vos as modificações desejadas.
Uma das grandes vantágens da classe Text sobre a classe Existe uma classe chamada LineSegment no framework gráfico Linhas
String além do fato dela poder sem enfatizada de diverças formas está que representa um segmento de linha. Ela é a abstração geométrica do
no fato de que Text implementa a mensagem ‘display: on:’, o que fornece conceito da menor distância entre dois pontos.
regularidade concomitante as outras classes que representam objetos Podemos criar instâncias da classe LineSegment enviando a
gráficos, desta forma, para escrevermos utilizar esta mensagem para mensagem de classe ‘from: to:’ ou ‘with: with:’. Usamos a primeira
quando existe a necessidade de se fazer diferenciação entre o ponto ini-

230 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 231


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

Método Descrição
permite que se defina a posição inicial e final onde
emphasizeFrom: to: with: se deseja enfatizar e aceita um ou vários tipos de
ênfases.
retorna um símbolo ou array de simbolo indi-
emphasisAt: quando qual ou quais tipos de enfase o caracter
cujo indice é passado como argumento possui.
aceita associações entre o simbolo #color e uma
emphasizeAllWith:
cor correspondente para colorir o texto.
allBold coloca todo o texto em negrito
verifica se o texto passado como argumento está
sameEmphasisAs: enfatizado de maneira igual ao texto que recebe a
Figura 12.4 Resultado do código do exemplo anterior mensagem.
Tabela 12.4 Métodos que mudam o estilo de uma instância de Text
cial e o final da linha. Porém não houver esta necessidade, ou ainda se
ela for indesejada, a segunda mensagem é a melhor opção. Método Descrição
Instancias da classe LineSegment são úteis no caso de dese- length retorna o comprimento da linha (módulo)
jarmos desenhar repretitivamente este objeto, mas também para perfa- verifica se a linha intercepta um retângulo que deve ser
zer operações geométricas como verificar se a linha intercepta um outlineIntersects:
passado como argumento
retangulo, inquiri-la sobre seu comprimento, etc. A tabela 12.5 apresenta
start retorna o ponto inicial da linha
alguns destes método.
end retorna o ponto final da linha
Como veremos mais a diante neste capítulo, objetos gráficos
Tabela 12.5 Métodos implementados por LineSegment
podem ser desenhados apenas delineados ou preenchidos, porém no
caso das linhas apenas a opção delineada é permitida. Para se desenhar
Uma das grandes vantagens da biblioteca de classes do Visu- Polígonos
linhas na tela podemos utilizar tanto uma instanica da classe LineSeg-
alWorks é sua regularidade. A semelhança do que ocorre com linhas,
ment ou o método displayLineFrom:to: da classe GraphicsCon-
polígonos podem ser desenhados de duas formas, a primeira é utilizando
text. As vantágens de se criar uma instância de LineSegment é a
instâncias da classe Polyline enviando a mensagem displayStroke-
mesma apresentada no caso dos textos.No caso em que desejamos
dOn:, a segunda é enviando a mensagem displayPolygon: ou
desenhar uma linha através de instâncias da classe LineSegment deve-
displayPolyline: ao contexto gráfico alvo. Em verdade o que as
mos utilizar a mensagem displayStrokedOn: e passar como argu-
mensagens displayFilledOn: e displayStrokedOn: é chamar
mento o contexto gráfico de destino. O exemplo 12.4 apresenta as duas
o método displayPolygon: ou o método displayPolyline: do
formas de criação de linhas e a utilização do método displayStroke-
contexto gráfico respectivamente, passado como argumento. Vale a
dOn: Linhas ainda podem ser transladadas e aumentadas. Estas opera-
pena dar uma olhada nestes métodos. Esta mesma estratégia de forne-
ções serão vistas mais à frente neste capítulo.

232 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 233


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

|line gc|

gc := (Examples.ExamplesBrowser prepareScratchWindow)
graphicsContext.

1 to: 800 by: 10 do:[:cont|


line := LineSegment from: 0@cont to: cont@0.
line displayStrokedOn: gc.

line := LineSegment
with:(400-cont)@0
with: 400@cont.
line displayStrokedOn: gc.
].

Exemplo 12.4 Mostrando linhas cruzadas

cer várias opções para uma mesma tarefa sem almentar a complexidade
da implementação é utilizada comumente em toda a biblioteca de clas-
ses.
A classe Polyline é utilizada para criar tanto polígonos como
coleções de linhas conexas (polylines). Porém em casos onde uma cole-
ção de linhas não ser fechada, ou seja, o ponto inicial coicidir com o final,
que atitude é tomada no caso de chamarmos o método displayFil-
ledOn: ? Figura 12.5 Desenho de linhas cruzadas gerado pelo código do exemplo anterior

Simples, implicitamente o ponto final da coleção de pontose interessante é alterar a mensagem display-StrokedOn: por
ligado ao ponto inicial, desta forma o coleção de linhas se fecha tor- displayFilledOn:. Faça isso e verifique o resultado.
nando-se um polígono e pode ser preenchida. Então podemos dizer que
Pológonos e coleções de pontos podem ser usados das mais
apenas poligonos podem ser preenchidos.
diversas formas. Lançando mão deles e de um pouquinho de matemática
Para criar tanto poligonos como coleções de linhas devemos podemos até mesmo criar curvas. A título de exemplo apresentamos um
enviar a mensagem vertices: à classe Polyline passando como programa que pode ser visto no exemplo 12.6. Ele cria uma curva ape-
argumento uma coleção de pontos. Em geral essa coleção pode ser uma nas utilizando uma instância de Polyline.
instância da classe OrderedCollection.
Existem muitos outros métodos úteis implementados na classe
O exemplo 12.5 mostra como podemos criar e apresentar Polyline, eles poder ser vistos na tabela 12.6 na página 238.
poligonos e coleções de pontos em um contexto gráfico. Um experimento

234 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 235


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

|col poli gc| "Desenha uma curva paramétrica cúbica de hermite"


|gc c1 c2 c3 c4 p1 p4 r1 r4 col x y pol |
gc := ( Examples.ExamplesBrowser prepareScratchWindow )
graphicsContext. gc := (Examples.ExamplesBrowser prepareScratchWindow)
graphicsContext.
col := OrderedCollection new.
p1 := 100@100.
col add: 10@10; p4 := 200@100.
add: 30@10; r1 := 0@1000.
add: 40@30; r4 := 0@1000.
add: 30@50; col := OrderedCollection new.
add: 10@50;
add: 0@30. 0 to: 1 by: 0.01 do: [:t|
c1 := ((2 *(t raisedTo:3)) - (3 * (t raisedTo: 2)) + 1).
poli := Polyline vertices: col. c2 := ((3 * (t raisedTo: 2)) - (2 * (t raisedTo: 3))).
poli displayStrokedOn: gc. c3 := (( t raisedTo:3) - (2 * ( t raisedTo: 2 ) ) + t).
Exemplo 12.5 Mostrando polígonos c4 := (( t raisedTo: 3) - ( t raisedTo:2 ) ).
x := ((p1 x) * c1) + ((p4 x) * c2)+((r1 x) * c3) +
Retângulos A classe Rectangle é a abstração de um retângulo geométrico ((r4 x) * c4).
existente no framework gráfico do Smalltalk. Não existe uma classe y := ((p1 y) * c1)+((p4 y) * c2)+((r1 y) * c3) +
((r4 y) * c4).
específica para representar quadrados, mas eles podem ser facilmente
col add: (x@y).
criados fazendo com que a larguma e o comprimento de uma instância
].
de Rectangle sejam iguais.
Existem vários métodos de classe para a instanciação de retân- pol := Polyline vertices: (col asArray).
gulos. Pode-se utilizar a mensagem origin: corner: que espera pol displayStrokedOn: gc.
dois pontos como argumentos, o primeiro deve ser o canto superior Exemplo 12.6 Desenha uma curva cúbica paramétrica (Hermite)
direito e o segundo o inferior esquerdo ou origin: extent: que
também espera dois pontos como argumentos. O primeiro é o canto instância de Rectangle tendo como canto superior esquerdo o ponto que
superior esquerdo e o segundo é a largura (coordenada x do ponto) e recebeu a mensagem e o ponto passado como argumento sendo o canto
altura (coordenada y do ponto). inferior direito. A classe Point também implementa a mensagem ‘extent:’
onde o ponto que é esperado como argumento tem sua coordenada x
Em casos onde não se deseja fazer diferenciação entre qual éo como sendo a largura e o y como altura do retângulo.
ponto inicial e qual o ponto final podemos utilizar a mensagem vertex:
vertex: Retângulos podem ser desenhados delineado ou preenchidos.
Para desenhar um retângulo delineado envie a mensagem displayS-
Existem muitas outras formas de se criar retangulos. Por exem- trokedOn: passando como argumento o contexto gráfico alvo e para
plo, a classe Point implementa a mensagem corner: que retorna uma

236 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 237


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

Método Descrição
vertices retorna uma instância de Array contendo todos os pontos
do poligono
verticesDo: avalia o bloco passado como argumento para cada par de
vértices do polígono
edgesDo: avalaia o bloco passado como argumento para cada ponto
do polígono
outlineIntersects: verificar se o polígono intercépta o retângulo passado
como argumento quando em forma de linhas
regionIntersects: o mesmo que o anterior porém quando preenchido
Tabela 12.6 Métodos implementados por Polyline
desenha-lo preenchido envie a mensagem displayFilledOn:. A
classe GraphicsContext também implementa o método displayRec-
tangle: para desenho de retângulos. O exemplo 12.7 mostra como
podemos criar e apresentar alguns retângulos.

|rect gc|

gc := (Examples.ExamplesBrowser prepareScratchWindow)
graphicsContext.
Figura 12.6 Resultado da execução do código de geração de retângulos
rect := Rectangle vertex: 10@10 vertex: 100@100.
rect displayFilledOn: (gc paint: (ColorValue red)). Existem também classes para representar alguns tipos de cur- Curvas Bézier
vas. O VisualWorks implementa as classes Bezier e Spline que são dois e Spline
gc paint: (ColorValue green). tipos de curvas muito utilizadas na prática. Como são curvas e não se
(110@10 extent: 50@50) displayStrokedOn: gc. espera que sejam fechadas elas não implementam o método ‘displayFil-
ledOn:’. Então para apresentam qualque uma destas curvas devemos
rect := Rectangle origin: 10@110 corner: 160@200. utilizar a mensagem ‘displayStrokedOn:’.
gc displayRectangle: rect at: 100@100.
Foge do escopo deste livro uma detalhada explicação sobre a
Exemplo 12.7 Criando e mostrando retângulos
fundamentação matemática destas curvas, mas caso o leitor deseje
Existem ainda muitos outros métodos úteis implementados pela saber mais pode consultar a bibliografia ao final do livro, em especial o
classe Rectangle. A tabela 12.7 na página 240 sumariza alguns deles. livro de computação gráfica. O exemplo 12.8 mostra como podemos criar
uma curva de Bézier e mostra-la na tela e o exemplo 12.9 mostra uma
curva spline cúbica.

238 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 239


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

Método Descrição "Desenhando uma curva paramétrica spline"


area retorna a área do retângulo |col spl gc|
gc := (Examples.ExamplesBrowser prepareScratchWindow)
bottom retorna a coordenada y da reta infeferior do retângulo. graphicsContext.
bottomCenter retorna o ponto métido ra reta horizontal inferior. col := OrderedCollection new.
center retorna o ponto do centro do retângulo. coladd: 10@100;
add: 50@110;
corner retorna o ponto inferior direito do retângulo. add: 70@190;
extent retorna um ponto representando o comprimento e altura do add: 80@100;
retângulo add: 110@200;
height retorna a altura do retângulo add: 130@100;
add: 170@0;
origin retorna o ponto superiror esquerdo do retângulo add: 410@100.
width retorna a largura do retângulo spl := Spline controlPoints: (col asArray) .
areasOutside: retorna uma coleção de retângulos externas ao retângulo spl displayStrokedOn: gc.
passado como argumento e internas ao retângulos que rece- Exemplo 12.9 Desenhando uma curva paramétrica spline
beu a mensagem.
contains: veritica se o retângulo passado como argumento está contido
dentro do retângulo que recebeu a mensagem
containsPoint: verifica se o ponto passado como argumento está contido
dentro do retângulo que recebeu a menságem.
intersects: verifica se o retângulo que recebeu a mensagem intercepta o
retângulo passado como argumento
Tabela 12.7 Métodos implementados pela classe Rectangle

|bez gc|

gc := (Examples.ExamplesBrowser prepareScratchWindow)
graphicsContext.

bez := Bezier start: 10@100 end: 300@10


controlPoint1: 100@0 controlPoint2: 130@200.
bez displayStrokedOn: gc.
Exemplo 12.8 Desenhando uma curva paramétrica de Bézier
Figura 12.7 Curva spline gerada pelo código do exemplo anterior

240 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 241


Superfícies gráficas, contexto gráfico e primitivas gráficas Objetos Gráficos

Transforma- Todos os objetos geométricos apresentados até aqui possuem | rct gc|
ções geomé- métodos para gerenciamento de transformações geométricas. Todas gc := (Examples.ExamplesBrowser
tricas estas classes possuem algumas transformações básicas salvo a classe prepareScratchWindow) graphicsContext.
Rectangle que possui uma gama de métodos mais elaboradas, em parte rct := Rectangle origin: 10@10 corner: 100@100.
por sua simplicidade geométrica e mais iportante que isso, pela sua rct displayStrokedOn: gc.
extensa aplicabilidade por toda a biblioteca de classes. A seguir apresen- (rct translatedBy: 100@100) displayStrokedOn: gc.
taremos as transformações básicas que todas as classes geométricas Exemplo 12.11 movimentando retângulos do contexto gráfico
implementam e em seguida apresentaremos mais algumas específicas
da classe Rectangle. Método Descrição
Podemos por exemplo ecalar qualquer objeto geométrico com o Espera um ponto ou escalar como argumento e retorna
scaledBy:
auxílio da mensagem scaledBy: . Esta mensagem espera como argu- um novo retângulo expandido.
mento um ponto que será multiplicado pelas coordenadas do objeto geo- Espera um ponto, escalar ou retangulo como argumento e
métrico. O exemplo 12.10 mostra como podemos escalonar uma figura. expandedBy: retorna um novo retângulo que esta fora do retângulo que
recebeu a mensagem por delta.
| rct gc| Espera um ponto, escalar ou retangulo como argumento e
insetBy:
gc := (Examples.ExamplesBrowser retorna um novo retângulo contido em delta.
prepareScratchWindow) graphicsContext. verifica se o retângulo que recebeu a mensagem interseci-
rct := Rectangle origin: 10@10 corner: 100@100. intersect: ona o retângulo passado como argumento e retorna um
rct displayStrokedOn: gc. boleano.
(rct scaledBy: 2@3) displayStrokedOn: gc
retorna um novo retângulo que contém tanto o retângulo
Exemplo 12.10 Escalonamento de um retângulo
merge: que recebe a mensagem como o que é passado como
Outra transformação geométrica suportada é a translação. Utili- argumento.
zando a mensagem trasnlatedBy: que espera como argumento um retorna uma coleção de retângulos que não estão contidos
ponto, podemos movimentar uma figura geométrica pelo contexto grá- areasOutside: dentro do retângulo passado como argumento e que estão
fico. O ponto passado como argumento para a mensagem indica o mon- dentro do retângulo que recebe a mensagem.
tante em pixels que a imagem será deslocada. Se o valor das Modifica o canto inferior direito do retângulo de modo que
coordenadas for positivo, a figura será deslocada para baixo e para a moveBy: sua área se adeque relativa a uma translação idicada pelo
direita, em contrapartida, se o valor for negativo, a figura será deslocada ponto passado como argumento
para cima e esquerda. O exemplo 12.11 mostra como podemos deslocar Move o retângulo de mode que o canto superior direito
moveTo:
um retângulo. seja o ponto passado como argumento
Como dissemos anteriormente, a classe Rectangle possui ainda retorna um novo retângulo que é transladado entre a sub-
align:with:
algumas outras rotinas de transformações geométricas. Por seu funcio- tração dos pontos passados como argumento.
namento ser intuitivo, apenas as listaremos na tabela 12.8 e fornecere- Tabela 12.8 Algumas outros métodos da classe Rectangle
mos uma breve explicação.

242 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 243


Superfícies gráficas, contexto gráfico e primitivas gráficas Imagens

Algumas destas mensagens podem não ser intuitivas, por isso Para apresentarmos a instancia de GraphicsAttributesWra-
sugerimos que o leitor experimente alguns exemplos, utilizando-os para pper devemos utilizar a mensagem displayOn: at: que espera
uma melhor compreenção de seu funcionamento. como argumento um contexto gráfico e um ponto a partir de onde será
desenhado o objeto. O exemplo 12.12 mostra como estas tarefaz podem
Wrappers Wrappers gráficos permitem que empacotemos objetos para ser executadas.
gráficos e facilitar seu processo de apresentação em om contexto gráfico. Duas
wrappers de classes são de particular interesse, a classe StrokinWrapper e a classe |gc rect wrp atr|
atributos FillingWrapper. Elas permitem-nos que definamos se um objeto gráfico gc := (Examples.ExamplesBrowser
gráficos dever ser apresentado apenas delineado ou preenchido. A utilização de prepareScratchWindow) graphicsContext.
wappers permite ao visualWorks fornecer uma interface de apresentação rect := Rectangle origin: 10@10 corner: 100@ 200.
uniforme para todos os objetos gráficos. A utilização de wrappers gráfi- wrp := GraphicsAttributesWrapper on: rect asFiller.
cos foi apresentada dutante a apresentação dos objetos geométricos em atr := GraphicsAttributes new paint: ColorValue red.
wrp attributes: atr.
geral. em suma devemos utilizar as mensagens asStroker ou asFil-
wrp displayOn: gc at: 0@0.
ler para obter um objeto geométrico empacotado dentro de um wra-
Exemplo 12.12 utilizando wrappers de atributos gráficos
pper.
Não devemos armazenar o contexto gráfico diretamente em uma
variável, pois como ele é contantemente alterado, não corespoderá ao 12.4 Imagens
que esperavamos que fosse. Então como podemos armazenar as confi-
gurações gráficas de um objeto que criamos? Devemos ter que manual- Imagens são matrizes de pixels contendo cores a seprem apre-
mente setar todas as propriedades toda vez que formos desenhar sentadas em uma área retângulor dentro de um contexto gráfico. Tem
nossos objetos gráficos? Embora esta seja uma alternativa, o Smalltalk como características serem armazenadas dentro do arquivo imagem. Por
fornece-nos uma maneira mais simples de resolver este problema. Pode- este motivo, imagens podem ser utilizadas para armazenar Pixmaps e
mos utilizar um wrapper gráfico. A classe que implementa wrappers gráfi- máscaras. Elas podem ser baseadas em cores ou índices, o que significa
cos é GraphicsAttributesWrapper. A idéia por traz é simples. Devemos que podem conter a cor do pixel a ser apresentado ou uma entrada em
criar nosso objeto gráfico normalmente utilizando as mensagens asS- uma paletta de cores.
troker ou asFiller. Isso nos retornará um objeto geométrico empacotado. Imagens são comumente utilizadas para criar cursores e icones,
Em seguida devemos criar uma instancia de GraphicsAttributesWra- assuntos estes que serão arordados mais a frente neste capítulo. A
pper impacotando o wraper anterior que contém o objeto geométrico. De classe abstrata Image define a interface para a criação de imagens.
posse do wrapper de atributos gráficos devemos criar uma instancia de Porém quem realente cria as imagens são suas subclasses concretas
GraphicsAttributes que conterá os atributos gráficos a serem atribuidos que realmente fazem o trabalho, criando desta forma imagens de diferen-
ao objeto geométrico previamente criado. Isso pode ser feito através da tes resoluções. A figura 12.8 mostra a hierarquia das classes de ima-
mensagem é paint: e espera como parâmetro uma cor ou um padrão. gens.
Por ultimo devemos instalar os atributos gráficos na instancia de Gra-
phicsAttributesWrapper. Isso depo ser feito através da mensagem attri- Imagens são armazenadas dentro do arquivo imagem do Small-
butes: passando a instancia de GraphicsAttributes como argumento. talk. Desta forma são vistas como recursos. Existem vantágens e des-

244 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 245


Superfícies gráficas, contexto gráfico e primitivas gráficas Imagens

A classe Image trabalha em cooperação com a classe Screen Capturando


Object para permitir-nos que, com o auxilio do mouse, possamos capturar peda- imagens da
ços de imagens que estão sendo mostradas no monitor naquele instante. tela
VisualComponent
O mecanismo para perfazer esta tarefa é simples, e sem dúvida este é o
PixelArray exemplo mais utilizado para mostrar as funcionalidades gráficas do
Image Smalltalk. Podemos capiturar a tela enviando a mensagem fromUser
para a classe Image. O cursor do mouse irá mudar para uma cruz e o
Depth16Image usuário pode então clicar o botão direito do mouse arrastá-lo marcando a
área a ser copiada e solta-lo. No momento que o botão do mouse imadi-
Depth1Image
atamente, uma instancia de Image será gerada e rotornada. Vale uma
Depth24Image ressalva, o retâgulo marcado deve ir do canto superiror esquerdo para
Depth2Image quando o botão do mouse for prescionado e deve ser solto no canto infe-
Depth32Image rior direito. O exemplo 12.13 mostra a operação.
Depth4Image
| gc im |
Depth8Image gc := (ExamplesBrowser prepareScratchWindow) graphicsContext.
Figura 12.8 Hierarquia das classes de imagem em Smalltalk im:= Image fromUser.
im displayOn: gc.
vantágens nesta abordagem. Uma vantágem, é que sua manipulação é Exemplo 12.13 Capturando uma imagem da tela
rápida se comparada com instanicas de Pixmap ou Mask. Ela pode ser
utilizada para salvar temporáriamente instancias de Pixmap e Mask que Uma outra abordagem, e talvez a mais usada por programado- Criando
de outra forma seriam perdidas ao fecharmos e abrirmos o visualWorks. res é criar imagens manualmente. A gama de maneiras distintas que nos imagens
Como desvantágem o arquivo imagem crescerá muito em seu tamanho permitem executar esta tarefa é bem extensa. O exemplo 12.14 mostra programati-
dependendo do tamanho da imagem e da resolução. como utilizando a mensagem extent: depth: palette:podemos camente
criar uma imagem em branco.
Criando Imagens podem ser criadas de três formas distintas. Através de
imagens um editor de imagens como o Image Editor que pode ser acessado atra- | im pal|
vés do UIPainter ou do VisualLaucher, capiturando diretamente pixels do pal := Screen default colorPalette.
buffer do monitor ou manualmente
im := Image
A utilização do Image Editor é intuitiva e já foi explicada no capí- extent: 8@8
tulo 3. Agora passemos a algo mais interessante, vamos ver como pode- depth: (pal depth)
mos capiturar imagens diretamente do buffer do monitor. palette: pal.
^im.
Exemplo 12.14 Criando uma imagem em branco

246 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 247


Superfícies gráficas, contexto gráfico e primitivas gráficas Imagens

No exemplo anterior, a imagem criada não continha qualquer fiquemos o tamanho da imagem (que deve ser um ponto onde a coorde-
desenho, apenas definimos a paletta das possíveis cores que ela pode nada x indica o numero de linhas e a coordenada y o numero de
conter e seu tamanho. Podemos também definir explicitamente qual será colunas), o número de bits por pixel, a paletta a ser utilizada e os bits da
o desenho que a imagem conterá. O exemplo 12.15 criar um X dentro de figura.
um retângulo. Neste método, duas considerações devem ser feitas. A palavra
chave bits: espera como argumento uma instancia de ByteArray.
| gc image | Este objeto deve conter todos os bits da imagem. Estes bits devem estar
gc := (ExamplesBrowser prepareScratchWindow) graphicsContext. organizados em bytes, então como no exemplo 12.15 o número de bits
por pixel é 1, cada byte representará 8 pixels. Caso o número de bits por
image := Image
pixel fosse 24, precisaíamos de 3 bytes para representar cada pixel.
extent: 16@16
depth: 1 Agora vejamos o conceito de pad. O Smalltalk espera que as
palette: CoveragePalette monoMaskPalette linhas de uma imagem sejam multipas de 32 bits, isso por motivos de
bits: #[ performance.Então quando o número de bytes nas linhas da imagem não
2r11111111 2r11111111 forem multiplos de 32 devemos especificar um valor de pad, que fará a
2r11000000 2r00000011 correção. Estes valores devem ser 8, 16 ou 24, que são respectivamente
2r10100000 2r00000101 1, 2 ou 3 bytes. Se por exemplo em uma imagem as linhas contiverem 3
2r10010000 2r00001001
bytes (24 bits) o valor de pad deverá ser 8 pois é o que falta para o
2r10001000 2r00010001
número de bits na linha ser multiplo de 32.
2r10000100 2r00100001
2r10000010 2r01000001 O exemplo 12.16 mostra uma figura com 3 bytes por linha, logo
2r10000001 2r10000001 o valor de pad deve ser 8 para completar um número multiplo de 32 bits
2r10000001 2r10000001 por linha. Quando o número de bits por linha é multiplo de 32, ou seja,
2r10000010 2r01000001 32, 64, 128, etc, não existe a necessidade de se especificar um valor de
2r10000100 2r00100001 pad, logo devemos utilizar a mensagem extent: depth: palette:
2r10001000 2r00010001 bits:.
2r10010000 2r00001001
2r10100000 2r00000101
2r11000000 2r00000011 No capítulo sobre arquivos externos vimos uma forma de ler Abrindo
2r11111111 2r11111111] uma imagem no formato PGM, lendo-a passo a passo. Existe também a imagens de
pad: 16. possibilidade se abrirmos imagens contidas em arquivos em alguns for- arquivos
matos padrão utilizando métodos de mais alto nível. Para tal, utilizamos a
image displayOn: gc at: 10@10. classe ImageReader. Ela nos pertimte que facilmente abramos imagens
Exemplo 12.15 criando uma imagem bit a bit tipo .bmp, .gif, .tiff, etc. O exemplo 12.17 abre uma imagem tipo bmp. A
figura 12.9 mostra a execução do exemplo 12.17.
No exemplo anterior, utilizamos a mensagem extent:
Agora que já vimos como criar e abrir uma imagem, vejamos
depth: palette: bits: pad:.Esta mensagem espera que especi-
mais alguns conceitos. Em uma imagem, cada pixel possui um valor que

248 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 249


Superfícies gráficas, contexto gráfico e primitivas gráficas Imagens

| gc image |
gc := (ExamplesBrowser prepareScratchWindow) graphicsContext.

image := Image
extent: 24@16
depth: 1
palette: MappedPalette whiteBlack
bits: #[
2r11111111 2r11111111 2r11111111
2r11000000 2r00000011 2r11111111
2r10100000 2r00000101 2r11111111
2r10010000 2r00001001 2r11111111
2r10001000 2r00010001 2r11111111
2r10000100 2r00100001 2r11111111
2r10000010 2r01000001 2r11111111
2r10000001 2r10000001 2r11111111
2r10000001 2r10000001 2r11111111
2r10000010 2r01000001 2r11111111
2r10000100 2r00100001 2r11111111
2r10001000 2r00010001 2r11111111
2r10010000 2r00001001 2r11111111
2r10100000 2r00000101 2r11111111
2r11000000 2r00000011 2r11111111 Figura 12.9 execução do exemplo 12.17
2r11111111 2r11111111 2r11111111]
pad: 8. uma tabela de cores são usados para permitir que imagens de mesma
resolução apresentem cores distintas. Por exemplo, uma imagem de
image displayOn: gc at: 10@10. depth 4 pode possuir até 16 cores simultaneamente. Mas quais dentre
Exemplo 12.16 Imagem com 3 bytes por linha todas as cores possíveis são essas tal 16 cores? A resposta é simples,
qualquer uma. na imagem ficam apenas armazenados indices para a
| gc image | tabela de cores que serão trocados por uma cor propriamente dita no
gc := (ExamplesBrowser prepareScratchWindow) graphicsContext. momento em que a imagem for ser desenhada em uma superfície de
image := (ImageReader fromFile:'e:\priest.bmp') image. apresentação.Isso nos permite por exemplo criarmos uma imagem depth
image displayOn: gc at: 10@10 4 em escala de roxo e outra em escala de laranja. O tipo de paleta deter-
Exemplo 12.17 Abrindo uma imagem de um arquivo mina em que tipo de superfície de apresentação a imagem pode ser
desenhada os lida. Se a imagem é baseada em índices de cores dize-
pode ser uma entrada em uma tabela de cores (paletta) ou uma entrada
mos que ela é compatível com Pixmaps janelas e , já se a imagem é
em uma tabela de coeficiente de transparência. Valores de entrada em

250 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 251


Superfícies gráficas, contexto gráfico e primitivas gráficas Cursores

baseada em coeficientes de transparência, ela será compatível com ins- | gc image ico|
tancias de Mask. gc := (ExamplesBrowser prepareScratchWindow) graphicsContext.
De posse de uma imagem podemos obter facilmente uma super- image := Image
fícei de apresentação bastando enviar a mensagem asRetainedMe- extent: 16@16
diun.O exemplo 12.17 abre uma imagem a partir de um arquivo, vamos depth: 1
palette: CoveragePalette monoMaskPalette
modifica-lo no exemplo 12.18 para obtermos uma instancia de Pixmap a
bits: #[
partir da imagem.
2r11111111 2r11111111
2r11000000 2r00000011
| image | 2r10100000 2r00000101
image := (ImageReader fromFile:'e:\priest.bmp') image. 2r10010000 2r00001001
image asRetainedMedium 2r10001000 2r00010001
Exemplo 12.18 Obtendo um pixmap através de uma imagem 2r10000100 2r00100001
2r10000010 2r01000001
2r10000001 2r10000001
12.5 Icones 2r10000001 2r10000001
2r10000010 2r01000001
Icones também são suportados pelo Smalltalk. A classe que 2r10000100 2r00100001
implemementa suas funcionalidades é Icon. Para trabalharmos com ico- 2r10001000 2r00010001
nes devemos ter uma imagem que possua uma paletta de transparên- 2r10010000 2r00001001
cias. Isso pode ser conseguido especificando-se a paletta da sequinte 2r10100000 2r00000101
maneira: 2r11000000 2r00000011
2r11111111 2r11111111]
CoveragePalette monoMaskPalette pad: 16.
De posse da imagem com paletta de transparências podemos ico := Icon image: image.
então criar uma instancia da classe Icon enviando a mensagem image: ico displayOn: gc at: 10@10.
para a classe Icon. O argumento deve ser uma imagem. Um ícone será Exemplo 12.19 icone a partir de uma imagem com paletta de transparências
retornado, e o mesmo pode ser associado a uma aplicação.
ocorrendo, ou quando o cursor do mouse está sobre algum objeto espe-
O exemplo 12.19 cria uma instância da classe Icon a partir da cial. No Smalltalk, existe a classe Cursos que nos permite alterar o cursor
imagem já muito usada de um X dentro de um quadrado. atual e também criar novos cursores. Para tal, devemos possuir uma
imagem com paletta de transparências.Existe ainda, muitos cursores
padrão que podem ser vistos na tabela 12.9.
12.6 Cursores Primeiro veremos como podemos utilizar os cursores padrão
Em aplicações profissionais, é muito comum alterarmos a apa- para alterar o cursor do mouse. Em seguida veremos como criar nosso
rência do cursor do mouse para indicar que algum processamento está próprio cursor onde também explicaremos o que vem a ser um hot spot.

252 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 253


Superfícies gráficas, contexto gráfico e primitivas gráficas Cursores

Utilizando os Todos os cursores apresentados na tabela 12.9 são implementa- ponda ao nome do cursor. Este campo não é necessário podendo ser
cursores dos na classe Cursor como variáveis compartilhadas de classe mas atribuido nil.
padrão podem ser acessado através de métodos de classe. Estes métodos
estão organizados sob o protocolo constants e são exatamente iguais |cur colorIm mskIm |
aos nomes dos cursores padrão apresentados na tabela 12.9. por exem- colorIm := Image
plo, para criarmos um cursor para coleta de lixo poderiamos avaliar a extent: 16@16
sequinte expressão: depth: 1
palette: MappedPalette whiteBlack
Cursor garbage bits:#[2r11111111 2r111111112r11000000 2r00000011
Para setarmos o cursor padrão do mouse podemos utilizar as 2r10100000 2r00000101 2r10010000 2r00001001
seguintes mensagens: 2r10001000 2r00010001 2r10000100 2r00100001
2r10000010 2r01000001 2r10000001 2r10000001
beCursor
2r10000001 2r10000001 2r10000010 2r01000001
show 2r10000100 2r00100001 2r10001000 2r00010001
showWhile: 2r10010000 2r00001001 2r10100000 2r00000101
2r11000000 2r00000011 2r11111111 2r11111111 ]
A mensagem beCursor indica a máquina virutal para usar o
pad: 16.
cursor que recebeu a mensagem como o cursor padrão. Já a menságem mskIm := Image
show muda imediatamente a aparência do cursor do mouse para a do extent: 16@16
cursor que recebeu a mensagem. Por último, a menságem sho- depth: 1
wWhile: espera um bloco como parâmetro e fará com que o cursor palette: CoveragePalette monoMaskPalette
tenha a aparência do cursor que recebeu a mensagem enquanto o bloco bits:#[2r11111111 2r11111111 2r11000000 2r00000011
retornar verdadeiro. 2r10100000 2r00000101 2r10010000 2r00001001
2r10001000 2r00010001 2r10000100 2r00100001
Criando um Caso os cursores padrão do Smalltalk apresentados neste capí- 2r10000010 2r01000001 2r10000001 2r10000001
cursor tulo não sejam suficientes, podemos criar nossos próprios cursores atra- 2r10000001 2r10000001 2r10000010 2r01000001
2r10000100 2r00100001 2r10001000 2r00010001
vés da mensagem image: mask: hotSpot: name:. A palavra
2r10010000 2r00001001 2r10100000 2r00000101
chave image: espera como argumento uma figura com uma paletta de
2r11000000 2r00000011 2r11111111 2r11111111 ]
cores, já a palavra chave mask: espera uma figura de mesmo tamanho pad: 16.
mas com uma paletta de coeficientes de transparência. Isso para que o cur := Cursor image: colorIm mask: mskIm hotSpot: 4@4 name:
cursor tenha aquela aparência de que está sobre as janelas e qualquer 'quadrado'.
outra coisa na tela. A palavra chave hotSpot: espera um ponto como cur showWhile: [(Delay forSeconds: 3) wait].
argumento e indica qual vai ser o ponto de ação do cursor. Se indicarmos Exemplo 12.20 Criando um cursor programacionalmente
o hotSpot como 0@0 o canto superior esquedo será tipo como ponto de
ação e assim por diante. Por último, name: espera uma string que corres-

254 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 255


Superfícies gráficas, contexto gráfico e primitivas gráficas Exercícios

Nome Aparência Nome Aparência Nome Aparência


12.7 Exercícios
blank hand topRight
1. Procure no System browser a implementação das primitivas gráficas
apresentadas neste capítulo e execute seus exemplos.Eles estão
bottomLeft marker up
organizados sob o protocolo Examples no lado de métodos de classe.
2. Crie um pequeno programa para escrever algo na tela utilizando ins-
bull normal wait tâncias da classe Text. Tente utilizar todas as funcionalidades para
textos vistas neste capítulo e verifique na classe outras que podemos
caret origin write utilizar.
3. Crie um programa para dezenhar algumas primitivas gráficas no can-
vas de exemplos.
compact- quickGarbage xeq
Memory 4. De posse do exercício anterior, aplica algumas transformações geo-
métricas nos objetos gráficos desenhados por ele.
corner read
5. Quando apresentamos as formas de criação de imagens dissemos
que uma imagem podia ser capiturada diretamente do buffer do moni-
crossHair scroll tor. A ferramenta Image Editor possui esta funcionalidade. Encontre-a
na ferramenta, teste seu funcionamento e em seguida procure a
dataBase square classe que implementa a Image Editor e veja a implementação da
funcionalidade. (Dica: Utilize o resource finder para encontrar a imple-
mentação do Image Editor).
down standardDrag 6. No capítulo anterior criamos a interface de um programa de dese-
nhos. Crie agora nesta aplicação a capacidade de se adicionar linhas
dropNotOk standar- e retângulos. Adicione uma nova tela onde pedimos as coordenadas
dDragCopy e então desenhe as figuras na tela. (Obs: para capiturar o contexto
gráfico do subcanvas execute a aplicação e em seguida inspecione a
earth thumbsDown
variável de instancia builder. Será um pouco complicado encontrar
uma referência ao subcanvas, mas o esforço lhe ensinará muita
garbage tumbsUp coisa)

Tabela 12.9 Cursores padrão

256 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 257


Superfícies gráficas, contexto gráfico e primitivas gráficas

Capítulo 13 &ULDQGR*8,V
,QWHUDWLYDPHQWH

Neste capítulo o leitor vai aprender quais são os recursos de pro-


gramação visual para montagem de interfaces de usuário disponibilizados
por VisualWorks através do UIBuilder e como utilizá-los. Ao final, o leitor
estará apto a criar rapidamente as mais elaboradas interfaces de usuário
para seus programas, incluindo-se aí tabelas, interfaces dinâmicas, jane-
las com gráficos e outros.

13.1 Criando uma GUI


O VisualWorks fornece-nos uma ferramenta RAD (Rapid Applica-
tion Development) para criação WYSYWYG de GUIs. Ela se chama UIPa-
inter e na versão 5i.3 final já vem carregada no arquivo-imagem. Caso o
leitor esteja uitlizando uma versão mais antiga do VisualWorks, deve carre-
gar o parcel correspondente para poder criar suas interfaces.
O UIPainter foi uma das primeiras feramentas RAD existentes,
inspirando a criação de muitas outras que hoje são amplamente utilizadas
no mercado. O funcionamento do UIPainter já foi apresentado no capítulo
3. O objetivo deste capítulo, é apresentar algumas outras funcionalidades

258 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Criando GUIs Interativamente Salvando a Janela como um Recurso

do UIPainter, tais como definir propriedades para widgets, como utiliza- windowSpec
las, apresentar o conceito de recursos e também trabalhar com multiplas "UIPainter new openOnClass: self andSelector: #windowSpec"
janelas.
<resource: #canvas>
^#(#{UI.FullSpec}
13.2 Salvando a Janela como um Recurso #window:
#(#{UI.WindowSpec}
O UIPainter trabalha em cooperação com o UIBuilder para criar #label: 'Canvas Exemplo'
interfaces gráficas. O que o UIPainter faz na realidade, é criar uma des- #bounds: #(#{Graphics.Rectangle} 412 284 618 449))
crição textual da interface, indicando os widgets presentes e também sua #component:
formatação. De posse desta descrição, o UIBuilder a traduz e transforma #(#{UI.SpecCollection}
em objetos, criando assim uma GUI.. #collection: #(
#(#{UI.SequenceViewSpec}
#layout: #(#{Graphics.Rectangle} 8 10
108 110 )
#useModifierKeys: true
#selectionType: #highlight )
#(#{UI.ActionButtonSpec}
#layout: #(#{Graphics.Rectangle} 137
130 186 155 )
#model: #btnOk
#label: 'OK'
#defaultable: true ) ) ) )
Exemplo 13.1 Definição de uma interface em sintaxe Smalltalk

gramador modifique este recurso de outra forma que não seja utilizando
Figura 13.1 Janela-exemplo o UIPainter.
Por exemplo, imagine que tenhamos criado a GUI mostrada na Para identificarmos se uma classe possui algum recurso de
figura 13.1 . O UIPainter cria então uma descrição textual para ela que interface devemos olhar no lado da implementação de classes da refe-
pode ser vista no exemplo 13.1. rida classe, procurarmos por um protocolo interface specs e verificarmos
se algum dos recursos listados possui um icone como o apresentado na
Para salvarmos uma janela como um recurso devemos executar
figura 13.2
a operação INSTALL. O que ela faz na realidade é criar a descrição tex-
tual da janela.
Note que qualquer alteração que for feita no arquivo textual refli-
tirá diretamente na aparência da tela, logo, não aconselhamos que o pro-

260 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 261


Criando GUIs Interativamente Propriedades

Figura 13.2 icone de recursos de interface

13.3 Reeditando uma Janela


De posse de uma interface, podemos reabri-la para edição de
diverças formas. Uma alternativa é no lado de implementação de clas-
ses, encontrar o recurso que desejamos editar. Devemos então clicar
sobre o mesmo com o botão direito do mouse e selecionar a opção edit
resource. Isso fará com que o UIPainter seja automaticamente aberto.
Note que esta técnica também se aplica a outros tipos de recurso, como
imagens, icones, cursores e menus.
Uma segunda alternativa é utilizar o Resource Finder. Esta é
sem dúvida a mais simples, pois permite-nos verificar todos os recursos
editáveis que residem em no arquivo imagem.No Resource Finder ainda
estão disponíveis várias outras opções como navegar a classe que
implementa o recuros e executá-lo (no caso de ser uma interface de apli-
cação)
Figura 13.3 Método de classe definindo uma interface gráfica para todas as instâncias
Existe ainda uma terceira maineira de se editar recursos que era
largamente utilizada em versões anteriores do VisualWorks e que hoje
caiu em desuso. Porém vejamos como podemos fazer isso. 13.4 Propriedades
A figura 13.3 apresenta a descrição textual da interface que cria-
Todo widget possui várias propriedades que ditam sua aparência
mos anteriormente. No comentário desta figura é incluido diretamente
e muitas vezes seu comportamento. Como a gama de propriedades varia
pelo UIPainter o comando necessário para editarmos o recurso logo
enormemente de widget para widget, decidimos nesta seção apresentar
abaixo do comentário. Então, basta que selecionemos o comentário
apenas algumas delas, deixando a cargo do leitor verificar o funciona-
(Note que devemos selecionar apenas a parte interna do comentário) e
mento das demais. Note que o esquema de propriedades é bem simples,
executemos através do menu acessível pelo botão direito do mouse, o
não implicando em umagrande dificuldade o entendimento das mesmas.
comando Do it. Desta forma o UIPainter será aberto para edição com o
referido recurso já carregado. As propriedades de um widget podem ser acessadas através do
menu associado ao botão direito do mouse. Devemos então selecionar o
widget que desejamos editar suas proriedades, clicar com o botão direito

262 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 263


Criando GUIs Interativamente Formatação e Espaçamento

do mouse sobre o mesmo e selecionar a opção properties. Isso fará com sagem de classe (que aqui deverá ser um símbolo com # na frente) que
que a janela apresentada na figura 13.4 seja aberta. retornará a imagem. Desta forma uma imagem será colocada sobre o
Na figura 13.4 vemos as propriedades de um botão. Neste botão. O campo ID indica um ponto de acesso ao widget através do
exemplo já podemos identificar algumas das mais importantes proprieda- UIBuilder. Devemos definir este campo se desejamos acessar o widget
des de um widget. A janela de propriedades é composta por um note- em questão programacionalmente. Ele também é conhecido como o
book para cada grupo de propriedades, ou seja, existem as propriedades nome do widget.
básicas do widget, seu esquema de cores, seu esquema de posiciona- Basicamente, todos os widgets possuem a aba basics com as
mento, etc. mesmas propriedades. Algumas outras propriedades mais avançadas
O campo string define a palavra ou grase que aparecerá no podem ser acessadas e definidas na aba Details. As abas Valitation e
botão. porém ainda podemos criar botôes com imagens. Neste caso notification servem para que definamos métodos que devem ser executa-
devemos selecionar o check box supplied byApplication. dos quando o estado do widget é alterado ou quando ele recebe o foco.
Em Color podemos defimor as cores do widget. Ele trabalha com um
esquema de foreground e gackground, inidicando a cor de fundo do wid-
get e a cor de frente. Em botôes o background define a cor do botão e o
foreground a cor do texto. A aba position merece uma atenção especial e
será abordada na próxima seção. Por último, a aba Dop Target permite-
nos configurar o esquema de drag and dop suportado pelo Smalltalk.

13.5 Formatação e Espaçamento


Esta sem dúvida nenhuma é a parte mais massante da edição
de uma interface gráfica. O UIPainter permite-nos que posicionemos
manualmente os widgets na janela. Porém, quando redimencionamos
um janela os widgets podem não ficar na posição desejada. Imagine por
exemplo que criarmos uma aplicação onde temos uma barra de opera-
ções que deve sempre ocupar o lado esquerdo de cima a baixo e um
widget text editor que deve ocupar o restante da janela. A configuração
deste exemplo pode ser observada na figura 13.5 .
Podemos criar facilmente a interface para a figura 13.5 . Agora o
que aconteceria se mandassemos espandir a tela ? Os widgets ficariam
Figura 13.4 Propriedades de um botão alinhados em relação ao canto superior esquerdo da tela, sem que seu
tamanho seja alterado. Porém podemos definir os widgets relativos pro-
Isso fará com que o campo string seja desconsiderado e o porcionalmente, isso fará com que ao maximizarmos a tela, eles conti-
campo message seja abilitado. Neste campo devemos indicar uma men- nuem ocupando-a toda. Para definirmos widgets proporcionais devemos

264 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 265


Criando GUIs Interativamente Formatação e Espaçamento

Figura 13.5 Interface-exemplo

entrar na janela de propriedades do widget e selecionar a aba position. A


figura 13.6 mostra as configurações para o widget text editor.
O funcionamento do mecanismo de posicionamento de widgets
é um tanto confuso até que entendamos seu espírito, porém não apre- Figura 13.6 Aba de proporções e posição de um widget
senta nenhuma dificuldade adicional se comparado a outras linguagens
de programação. na janela de propriedades aba position, podemos ver
duas colunas distintas: Proportion e offset. A primeira dita qual a propor- Left@Top
ção da tela que o widget irá utilizar e a segunda é um offset de desloca-
mento. Caso o lado de proportion esteja em 0 significa que não estamos
utilizando o esquema de proporção e o offset é tipo como a posição em
pixels do ponto.
Podemos ver um widget como um retângulo onde precisamos
apenas de dois pontos para posiciona-lo na tela. A figura 13.7 mostra as Right@Bottom
convenções adotadas pelo Smalltalk em relação às coordenadas dos
Figura 13.7 Filosofia de definição de tamanho através dos cantos de objetos
widgets.
Desta forma, podemos concluir que no nosso exemplo, o canto ele proporcionalmente 1 que indica que toda a tela deve ser utilizada. O
superior esquerdo do widget text editor é fixo sempre no pixel 144@6. Ja esquema de proporções funciona da seguinte maneira:
o canto inferior esquerdo deve ocupar todo o resto da janela pois definior
0 - indica que não utilização esquema de proporções

266 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 267


Criando GUIs Interativamente Definindo Propriedades e Value Holders

0.25 - indica que o widget deve ocupar 25% da tela


13.6 Definindo Propriedades e Value Holders
0.50 - indica que deve ser utilizado 50% da tela
1.0 - espaço restante ao canto oposto deve ser utilizado. O UiPainter trabalha em conjunto com o UiBuilder para facilitar a
vida dos programadores. Desta forma, existe um esquema conhecido
Qualquer valor intermediário pode ser utilizado, pois o esquema como DEFINE e que já foi apresentado brevemente no capítulo 3, que
de proporções trabalha com uma escala de números reais indo de 0 a 1. nos permite criar pontos de acesso para os mais diverços widgets.
O UiPainter possui ainda algumas ferramentas muito úteis para Revisando o processo previamente esplicado, a idéia é selecio-
formatar seus widgets na janela. A exemplo 13.8 apresenta-a. nar o componente para o qual desejamos criar um método de acesso e
então selecionar a opção define. Isso fará com que um método de instan-
cia seja adicionado a classe que implementa sua interface e é a partir de
onde devemos acessar os dados dos widgets.
Figura 13.8 Ferramentas de alinhamento e espaçamento Também podemos acessar propriedades dos widgets em tempo
de execução através da variável de instancia builder que toda inter-
Seu funcionamento é bem simples e intuitivo permitindo que face gráfica criada com o UIPainter possui, porém este método é bem
apenas por inspeção visual entendamos o que elas fazem. Vale a pena baixo nível só devendo ser utilizado em última instancia.
dar uma testada em todas elas pois poupam-nos muito trabalho tentando
Para os widgets, o VisualWorks trabalha com o esquema de
deixar todos os componentes alinhados e de mesmo tamanho.
valueHolders, ou seja, o widget está inserido dentro de um container.
Ainda com relação a formatação e posicionamento, o Smalltalk Isso fornece as aplicações uma homogeneidade no tratamento de wid-
nos fornece uma maneira de agruparmos vários widgets em um grupo, gets visto que para acessar dados de quase todos os widgets necessita-
que a partir do momento que estão agrupados, passam a ser para o mos apenas enviar a mensagem value para o mesmo.Para
UIPainter no tocante a posicionamento, como um único widget. Esta entendermos melhor o funcionamento deste esquema de value holders
característica é muito útil em situações onde após formatarmos alguns vejamos o exemplo apresentado a seguir. Ele é bem simples. Criarmos
widgets na posição que desejamos, não desejamos mais ter que execu- um canvas contendo um ListBox, um input field e um botão. Toda vez
tar a tarefa de reformata-las novamente. Uma ver agrupados, os widgets que clicamos no botão o texto do input field é adicionado ao list box.
podem ser movidos livremente pelo canvas. Para agrupar widgets, sele- Embora este exemplo possa ser de pouca utilizade prática, ele nos per-
cione-os com o mouse. Em seguida acesse o item de menu mitivá observarmos o funcionamento do esquema de value holders.
<Arrange>>><group>.
A figura 13.9 mostra como deve ficar a interface do nosso exem-
Ainda podemos agrupar grupos menores dentro de um maior e plo, e o exemplo 13.2 o código para a criação do mesmo.
também podemos desagrupar widgets de um grupo no item de menu
Para o list box definimos seu aspect como lstStrings e para o
ungroup.
input box edtString. Para o botão definimos seu campo action como add.
Note que não precisamos fazer quase nada pois ao definirmos os wid-
gets no UIPainter estes métodos serão automaticamente criados. O
único método que reescrevemos foi o add. E este é nosso método de

268 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 269


Criando GUIs Interativamente Definindo Propriedades e Value Holders

"----------------------------------------------------------"
"Difinição da classe"
Smalltalk defineClass: #Teste2
superclass: #{UI.ApplicationModel}
indexedType: #none
private: false
instanceVariableNames: 'ck1 lstStrings edtString '
classInstanceVariableNames: ''
imports: ''
category: 'UIApplications-New'
Figura 13.9 Janela do exemplo de value holders "----------------------------------------------------------"
"métodos de instancia"
interesse para entendermos como funciona o esquema de value holders. "----------------------------------------------------------"
A idéia é adicionar a string contida no input box na lista de strings do list add
box. O método add será executado toda vez que o botão for clicado e os lstStrings listHolder value add: (edtString value).
outros métodos servem unica e exclusivamente para acessar o valor do "----------------------------------------------------------"
input box e do list box. edtString
^edtString isNil
Agora, lembremos do mecanismo de encadeamento de mensa- ifTrue:
gens visto no capítulo 5 para podermos entender bem como o método [edtString := String new asValue]
add funciona. Em primeira instancia, enviamos a mensagem lis- ifFalse:
tHolder para o list box. Isso nos retornara um value holder contendo [edtString]
um objeto tipo List. Em seguida enviamos a mensagem value para o "----------------------------------------------------------"
value holder previamente obtido. Destaforma teremos em mão uma ins- lstStrings
tancia da classe List. Para adicionarmos um ítem a uma lista devemos ^lstStrings isNil
utilizar a mensagem add: , e para obtermos a string contida no input ifTrue:
[lstStrings := SelectionInList new]
box devemos enviar a mensagem value. Desta forma a string contida no
ifFalse:
input box será adicionada ao list box.
[lstStrings]
Vemos que praticamente só utilizamos a mensagem value e Exemplo 13.2 código do exemplo de value holders
valueHolders para perfazer esta nossa pequena tafera. Este mecanismo
é bem uniforme funcionando para praticamente todos os widgets do fra- taxe e quais variáveis um determinado objeto contém. Para fazer isso
mework de interfaces do VisualWorks. utilize a técnica do self halt vista anteriormente.
Uma boa prática de programação em Smalltalk é inspecionar
todo e qualquer tipo de objeto. Isso facilita enormemente a vida do pro-
gramador, pois desta forma ele não necessitará saber exatamente a sin-

270 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 271


Criando GUIs Interativamente Widgets

um determinado componente. Neste ponto o VisualWorks nos fornece


13.7 Controlando a Aparência da GUI uma rica gama de exemplos que podem ser acessado em forma de par-
Como o Smalltalk é multiplataforma, muitas vezes desenvolve- cels ou através do help on-line dentro do ambiente de desenvolvimento.
mos um aplicativo por exemplo em linux e ele rodará em windows. Para
estes casos onde desejamos saber como ficará a interface que criamos Nome Icone Descrição & Dicas
em outro sistema de janelas, o UIPainter possui a funcionalidade modifi- Action Button Botão fornecido pelo framework de interfaces. Uma boa
car o esquema de janelas. Isso pode ser feito através do ítem de menu, dica é que no momento em que definimos um botão
Look.A figura mostra uma janela em 3 sistemas de janelas distintos. (opção define) seu método de acesso se encontrará no
protocolo actions.
Check Box Botão de checagem. Para acessa-lo devemos definir um
aspect para o mesmo, Seu ponto de acesso será a men-
sagem que definimos na propriedade as pect e estará no
protocolo aspects.
Radio Button Também funciona com o esquema de aspects.
Default Look OSF Motif Macitosh
Label Este é um texto estático. Podemos acessá-lo através do
UIBuilder (variável de instanica builder) desde que defi-
namos um ID para ele
Input Field Caixa de texto. Também funciona com o esquema de
aspects. Ele ainda possui a capacidade de ter um menu
associado.
Text Editor Também funciona com o esquema de aspects. Aceita
texto formatado, ou seja, instancias da classe Text.
Figura 13.10 Esquema de janelas em 3 sistemas distintos
Menu Button Componente pouco usual no mundo Windows. Tem a
forma de um botão e associa um menu ao mesmo. Seu
funcionamento gráfico é parecido com o do combo box.
13.8 Widgets List Um dos componentes mais utilizados no VisualWorks.
Como uma abordagem individual de cada widget seria demasi- Permite multipla seleção de ítens e ainda tem a capaci-
ado extensa e massante decimimos apresetar cada widget de uma forma dade de possuir um menu associado.
resumida implicando em uma descrição de cada um e algumas dicas que Combo Box Meio chatinho de se utilizar. No VisualWorks existe um
poderão auxiliar o leitor no momento em que fo-los utilizar. bom exemplo de seu funcionamento
Uma regra geral deve estar em mente quando o leitor necessitar Divider Simplesmente uma linha horizontal ou vertical para
embelezar sua interface.
utilizar algum componente. Veja um exemplo. Vendo o funcionamento de
um exemplo fica bem mais simples aprendermos as particularidades de Tabela 13.1 Funcionalidades de Programação Visual de Interfaces em VisualWorks

272 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 273


Criando GUIs Interativamente Exercícios

Nome Icone Descrição & Dicas Nome Icone Descrição & Dicas
Group Box Serve para agrupar radio buttons ou para deixar sua Table Permite que agrupemos informações em forma tabutar.
interface mais profissional Bem chatinho de ser utilizado.
Region Permite que algumas formas geométricas sejam adicio- Dataset Automatiza algumas tarefas para manipulação de dados
nadas a sua interface. Dê uma olhada na aba Details da em um banco de dados.
janela de propriedades Note Book Permite que organizemos várias informações ou widgets
Slider Componente para variação de valores dentro de uma em um mesmo espaço na tela. Utilizado na janela de
faixa pré-definida. Ele é por exemplo utilizado na janela propriedades.
de posicionamento de widgets. View Holder Este componente é muito útil para quando criamos
Tabela 13.1 Funcionalidades de Programação Visual de Interfaces em VisualWorks alguma aplicação MVC e desejamos roda-la dentro de
nossa interface. É a abstraçao do View no referido
modelo
Subcanvas Como um canvas normal. Permite que abramos outras
interfaces dentro de nossa janela principal. Também
serve para embelezar a interface.
Spin Button Botão de incremento e decremento

Click widget Permite que adicionamos uma imagem em nossa aplica-


ção sensível a regiôes.
Button tab Note- Abas do notebook. Deve ser utilizado em conjunto com o
Book Notebook.
Hiearchical List Permite que organizemos e apresentemos informações
de forma hierarquica. Semelhante ao esquema usado no
windows explorer.
Percent done bar Barra de porcentagem.

Tabela 13.1 Funcionalidades de Programação Visual de Interfaces em VisualWorks

13.9 Exercícios
1. Crie uma aplicação simples e mande instala-la. Em seguida descubra
sob que categoria a mesma foi criada.Como faríamos para salvar
nossa aplicação sob uma categoria pré-escolhida?

274 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 275


Criando GUIs Interativamente

-DQHODVGHGLiORJR
2. Na aplicação anterior teste alguns dos widgets. Coloque-os no can-
vas e veja suas propriedades. Capítulo 14
3. No capítulo 11 ciramos uma aplicação para calcular o período a partir
de uma frequência pré-estabelecida. Crie agora um front end para o
mesmo.
4. Para executarmos uma aplicação com interface gráfica, podemos uti-
lizar o resouce finder, abri-la diretamente do UIPainter e ainda existe
uma outra maneira que por sinal, é a mais usada. Descubra como
devemos proceder para abrir uma aplicação por exemplo no works-
pace. (Dica verifique a hierarquia de classes. Selecione sua aplicação
e execute o comando spawn hiearchy. O método que estamos procu-
rando está na classe ApplicationModel)
5. Existe alguma variante do método encontrado no exercício anterior?
Se sim, liste-as.
6. Crie uma aplicação contendo uma barra de botôes na parte superior
da janela e um quandro de desenhos na parte inferior. Faça com que
a barra de ferramentas ocupe sempre o mesmo tamanho e po quadro Neste capítulo você vai aprender a utilizar as diferentes janelas de
de desenhos o restante da tela. (lembre-se do esquema de posiciona-
diálogo oferecidas por VisualWorks. Caixas de diálogo são janelas simplifi-
mento relativo). Para o quadro de desenhos utilize por exemplo um
cadas, que servem para apresentação de simples informações, tomada de
subcanvas.
decisões e entrada de dados simples. Elas são usadas com muita freqüên-
cia e sua utilização dá uma aparência mais profissional para suas aplica-
ções.

14.1 Caixas de Diálogo no VisualWorks


O VisualWorks possui algumas caixas de dialogo padrão que tor-
nam simples a criação e apresentação destas janelas. Muito embora exista
esta facilidade para a apresentação de caixas de diálogos, ainda existe
várias formas de se customizar as formas já existentes ou até mesmo criar
outra caixa de diálogo completamente nova. Na classe Dialog implementa
as mensagens padrão para a criação de caixas de diálogo.
Basicamente, podemos dividir caixas de diálogo em três grupos.
As janelas de Confirmação, as Janelas de Requisição e as janelas de

276 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Janelas de diálogo Janelas de Confirmação (confirm boxes)

Aviso. Vamos abordá-las uma a uma verificando como elas são instanci- alfa: novoAlfa
adas e o que elas podem nos fornecer.
(novoAlfa >= 0 & novoAlfa <=1)
ifFalse:[
14.2 Janelas de Aviso (warn boxes) Dialog warn: 'O valor do Alfa deve \estar entre zero e um.'
withCRs.
O uso das caixas de aviso é normalmente utilizada quando se ]
deseja retornar alguma informação para o usuário, como por exemplo ifTrue:[
uma confirmação de sucesso de uma operação. alfa := novoAlfa.
].
Exemplo 14.1 Método mostrando uma mensagem de erro que abre uma caixa de aviso

definições padrão do seu sistema gerenciador de janelas. Caso você


esteja trabalhando em uma aplicação que tenha estes padrões alterados,
como a cor da janela em amarelo, suas janelas de diálogo sempre serão
mostradas na cor padrão do sistema. Para remediar este problema e per-
mitir que suas janelas de diálogo também sejam amarelas, toma mensa-
gem que cria uma janela de diálogo tem uma variante com a palavra
Figura 14.1 Janela de aviso simples
chave for que recebe como parâmetro as definições do seu sistema,
Sua composição é simples, uma parte textual onde você indica a extraindo-as por exemplo da janela corrente. Abaixo apresentamos uma
informação a ser transmitida para o usuário e apenas um botão OK para maneira de se capturar as configurações do seu sistema:
fechar a janela. Em resposta a janela sempre retorna o objeto nil.
Para exemplificar o uso de janelas de aviso apresentaremos um
método que testa se o valor para Alfa está entre zero e um. Caso contrá- 14.3 Janelas de Confirmação (confirm boxes)
rio uma janela de aviso é aberta. O uso mais comum dado a caixas de confirmação é quando
Caixas de aviso, são sem dúvida o tipo mais simples de caixas ocorre algo em seu sistema e você deseja que o usuário tome uma deci-
de diálogo. Existem apenas duas variações de métodos para sua cria- são simples. Tais como sim ou não? Verdadeiro ou Falso? Alterar agora
ção, sendo que em um destes métodos apenas se especifica a aparência ou Mais tarde? Note que as caixas de confirmação não ficam presas a
que se deseja para a janela. perguntas com apenas duas respostas. Você pode definir uma lista delas
as quais o usuário deve escolher.
A outra mensagem para a criação de janelas de aviso é warn:
for: onde o argumento relativo a palavra chave for é uma instancia da Em seguida mostramos algumas das janelas de confirmação
classe ScheduledWindow ou da classe VisualPart. Esta variante de com que vocÊ se deparará no ambiente do Smalltalk.
janela de aviso se dá devido ao fato das janelas de aviso bem como
todos os outros tipos de janelas de diálogo sempre serem criadas com as

278 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 279


Janelas de diálogo Janelas de Multiplas Seleções

Figura 14.3 Janela de requisição de um novo Alfa

alteraAlfa
"método para a alteração do Alfa do perceptron"
Figura 14.2 Janelas de diálogo: Uma janela de pesquisa inválida, janela para escolha do tipo |novoAlfa|
de variáveis e uma janela de saida do ambiente.
novoAlfa := Dialog request:
'Preencha o campo com um novo Alfa'.
14.4 Janelas de Requisição (input boxes) self perceptron Alfa: (novoAlfa asNumber).
Exemplo 14.2 Código para a janela anterior
Em outros casos, pode ser requerido que o usuário digite uma
string em resposta a uma pergunta. A aparência padrão da janela é com-
posta por três regiões onde temos uma string explicativa que indica ao
usuário o que ele deve digitar, uma caixa de entrada para que a string
seja digitada e dois botões, um para cancelar a operação e outro para
confirmá-la.
Várias outras coisas podem ser feitas com janelas de requisição
tais como se definir uma resposta padrão ou definir uma ação a ser
tomada quando a opção cancelar é selecionada. Nestes casos, se asso-
cia ao botão cancelar um bloco que será avaliado caso o botão cancelar Figura 14.4 Janela para pesquisa de classes
seja selecionado.
Um outro exemplo de janelas de requisição que o leitor se depa-
rará a todo o momento em que estiver utilizando o ambiente de desenvol- 14.5 Janelas de Multiplas Seleções
vimento do VisualWorks será a janela para procura de uma classe. Quando a lista de seleções a que o usuário deve responder for
muito extensa e não puder ser representada por botões, uma opção são
as janelas de múltiplas sepeções. Nestes tipos de janelas, uma caixa de
listagem é apresentada contendo todas as possíveis seleções. O número

280 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 281


Janelas de diálogo

0HQXV
máximo de opções mostradas deve ser informado assim como o bloco a
ser validado caso o botão de cancelar seja clicado. A cada item da lista Capítulo 15
um valor deve ser associado..

Neste capítulo apresentaremos as duas maneiras que o Smalltalk


nos fornece para criarmos menus. Iniciaremos apresentando uma ferra-
menta muito útil para criação de menus chamada “Menu Editor‘, apresen-
taremos toda a potencialidade desta ferramenta e mostraremos como
Figura 14.5 Janela de múltipla seleção devemos proceder para salvar e acessar menus criados a partir dela. Em
seguida apresentaremos a segunda maneira de se criar menus, que con-
siste em criar programacionalmente o menu, ítens e subitens que deseja-
mos. Por fim apresentaremos os 3 tipos de menus suportados pelo
VisualWorks e como devemos proceder para adiciona-los a uma janela ou
widget.

15.1 Menus em Smalltalk


Menus correspondem a uma parte muito importante do Smalltalk.
Eles permitem que dinamicamente opções sejam apresentadas ao usuário
(como no caso dos menus popup) tomando praticamente nenhum espaço
na interface. Em outros casos, representam apenas uma pequena faixa na
parte superior da janela, e ainda podem ter a aparência de um botão.
Como já citamos anteriormente neste livro, menus são utilizados exausti-

282 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Menus Menus em Smalltalk

vamente por todo o ambiente de desenvolvimento do VisualWorks, e


como todo o ambiente foi escrito em Smalltalk, é de se esperar que as
classes referentes a manipulação de menus sejam práticas e fáceis de
usar.

Menu Editor A ferramenta Menu Editor permite que criemos e testemos rapi-
damente menus. Ela possui várias facilidades para reposicionamento de
itens, deleção, adição e alteração de ítens. Ela permite que definamos
um menu previamente criado como um recurso do sistema que pode ser
associado a vários widgets como veremos mais a frente neste capítulo.
O menu editor pode ser acionado a partir do Visual Laucher
selecionando o item de menu <Tools> >> <Menu Editor> ou a partir do
UIPainter selecionando o item de menu <Tools> >> <Menu Editor>.
Ele ainda pode ser aberto de uma terceira maneira. Se selecio-
narmos o recurso referente ao menu no system browser e clicarmos com
o botão direito do mouse sobre ele, temos então a opção <edit
resource>. Ao selecionarmos esta opção o menu editor será aberto com
a especificação do menu que o recurso representa.
Figura 14.1 O Menu Editor sobre um menu vazio
Logo que ele é aberto, temos a janela de definição de ítens em
branco para a criação de um novo menu, mas caso desejemos editar um deverá adotar e no campo value escreva um símbolo1. Quando este item
menu pré-existente basta que selecionemos o item de menu <Menu> >> de menu for selecionado um método de mesmo nome que este símbolo
<Load>. Isso fará que uma janela seja aberta para que endiquemos qual será executado. Explicaremos isso mais a frente neste capítulo.
menu de qual classe queremos editar. Uma maneira mais fácil de editar
Para criarmos subitens ao item previamente criado basta clicar-
um menu pré-existente é selecionar o recurso correspondente ao menu
mos no segundo botão da esquerda para a direita (veja figura 15.2 ). Um
no Resource Finder.
novo subitem será então adicionado.

Criando um Após abrirmos o menu editor podemos imediatamente começar Quando criamos um item de menu apenas para organizarmos
novo menu a criar os ítens do menu. Para isso utilizamos os 3 botões apresentados subitens não existe a necessidade de se definir um valor (campo value
na fig14.2. O primeiro botão da esquerda para a direita adiciona um novo visto anteriormente) para este item. Fica sendo necessário então apenas
item ao menu. Ao clicarmos neste botão um novo item será adicionado a definirmos o campo default.
lista da esqueda do menu editor. Ele aprarecerá como <new item>.
Podemos então nomear o item e definirmos um método a ser invocado
1. Lembre-se que simbolos devem começar com o caracter #, caso este caracter não
quando este item de menu for selecionado. Isso pode ser feito na parte seja digirado, o menu editor o inclui. Lembre-se de respeitar as regras para criação de
direita do menu editor. No campo Default, escreva o nome que o item símbolos vistas no capítulo 3.

284 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 285


Menus Menus em Smalltalk

resource. Outro dado interessante sobre recursos é que eles nada mais
Cria novo ítem Cria novo ítem de menu são que métodos. No caso de recursos tipo menu, o que eles fazem é
de menu abaixo como subítem do item
retornar uma instância da classe Menu.
do selecionado atualmente selecionado
Insere separador
abaixo do item
selecionado
Classe na qual
o menu será
Figura 15.2 Botões para a criação de itens de menu instalado como
recurso
Finder,
Barras para separação de itens podem ser facilmente criadas cli-
para pro-
cando no terceiro botão da esquerda para direita apresentado na figura curar por
15.2 . Eles não precisam ter nenhum campo definido, ficando a parte outra classe
direita do menu editor desabilitada. para instalar
Seletor do método
o menu
de classe que
Reposicio- Caso criemos um item ou subitem de menu em local errado vai definir o menu
nando, exclu- podemos movimentá-lo para que fique no local desejado, isso pode ser (se selecionado)
indo e feito através dos botões apresentados na figura 15.3 . Estes botões per-
editando mitem-nos por exemplo transformar um ítem em subitem e vice-versa.

Campo para entrar


com um novo seletor
de método para a
instalação do menu
Figura 15.3 Botões para reposicionamento dos itens de menu
Figura 15.4 Janela para instalação de um menu como recurso
Instalando o Uma vez que o menu está completamente definido podemos
menu como então instala-lo como um recurso em uma classe e posteriormente ligá-lo É bem facil identificar qual recurso representa o menu que aca-
um recurso a um widget qualquer que suporte menus ao a uma janela. Para salvar- bamos de criar. Basta, como acabamos de dizer, procurar na parte rela-
mos o menu criado basta que selecionemos o item de menu <Menu> >> tiva à implementação de classe, na classe em que o instalamos e
<Install>. A janela mostrada na figura 15.4 na página 287 será então verificar o protocolo resource. Ele terá um ícone igual ao apresentado na
aberta para que indiquemos em que classe desejamos instalar o menu e figura 15.5 .
qual o nome (selector) desejamos dar ao menu. Após definirmos estes
dois dados basta que cliquemos em OK.
Vale lembrar que qualquer recurso que uma classe possua fica
no lado da definição de classes no System Browser sob o protocolo Figura 15.5 Ícone que representa um menu como recurso

286 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 287


Menus Criando um Menu Programaticamente

Definindo Os menus que estamos acostumados a ver possuem ítens habi- possuir uma marca de checado (Initially On / Initially Off). A parte inferior
propriedades litados e desabilitados, ítens checados e ítens com imagens. O menu desta aba permite que iniciemos um item de menu abilitado ou desabili-
editor suporta todas estas funcionalidades para seus ítens de menu elas tado. O padrão caso não alteremos nada nas proriedades é o apresen-
podem ser definidas no momento em que criamos o menu ou alteradas tado na figura.
posteriormente programacionalmente. Na figura 15.7 vemos a aba de detalhes do item de menu seleci-
onado. Nela podemos definir um caracter de atalho para acesso ao item
de menu pelo teclado juntamene com a tecla <ALT>. Também existe uma
caixa nomeada label image. Ela permite que definamos uma imagem
para o item de menu. Como toda imagem em smalltalk é tratada como
um recurso, devemos indicar qual a classse onde o recurso está insta-
lado e qual o método que representa o recurso.

15.2 Criando um Menu Programaticamente


Basicamente podemos criar menus que retornem valores
quando um um de seus itens é selecionado ou retornem simbolos que
correspondem a nomes de métodos que serão executados em resposta
a um item selecionado.
Podemos criar menus de duas maneiras distintas, utilizando a
classe Menu diretamente, que é a maneira mais antiga e mais traba-
lhosa, ou utilizando a classe MenuBuilder que facilita bastante o pro-
cesso de criação de menus. Em verdade o menu builer é uma interface
que por tras trabalha com o menu builder e que por sua vez cria instan-
cias da classe Menu.
Figura 15.6 Aba de propriedades do Menu Editor

Nesta seção nos preocuparemos em apresentar como definir Instancias da classe Menu representam uma lista de instancias A classe
estes tipos de propriedades deixando as alterações no menu em tempo da classe MenuItem que por sua vez são apresentadas em um menu. Menu
de execução para mais adiante neste capítulo. Note que uma instancia isolada da classe MenuItem não é de muita utili-
dade. Os ítens de um menu podem ser agrupados nas mais variadas for-
Quando selecionamos um item de menu que acabamos de criar
mas, exatamente como vimos anteriormente neste capítulo.
a parte direita do menu editor fica abilitada. É nesta região do menu edi-
tor que poderemos definir como deverão aparecer os itens do menu. A Duas das variáveis de instancia da classe Menu nos são de par-
figura 15.6 mostra uma das abas de propriedades para os itens de menu. ticular interesse. A variável items é uma lista de instancias da classe
Nela podemos indicar se o item deve ser simples (none) ou se ele deve MenuItem que contém uma string com o textos que serão apresentados

288 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 289


Menus Criando um Menu Programaticamente

Cada item do menu possui um valor associado que será retor-


nado quando um ítem for selecionado. Este valor pode ser qualquer
Definição da objeto, sendo que se nenhum for atribuído, a posição do item na lista de
tecla de atalho itens do menu será retornada. Se um menu for aberto e nenhum item for
selecionado, o menu retornada o inteiro zero. Normalmente o valor asso-
ciado a um item é um símbolo que representa uma mensagem a ser
invocada quando o referido item do menu é selecionado. Um item de
menu pode sofrer várias alterações, como ficar temporariamente desabi-
Classe na qual litado, habilitado. Pode ser associado a um item de menu uma imagem
está definido o ou ter teclas de atalho associadas ou ainda ter a aparência de sua string
ícone deste ponto alterada com efeitos como negrito, sublinhado ou itálico.
de menu como
recurso A aparência de um menu como um todo também pode sofrer
alterações, como por exemplo ter a cor de fundo alterada, adicionar
novos itens ao menu ou excluir itens pré-existentes . Por definição, todos
Seletor de método os menus são criados seguindo as definições padrão do sistema, sendo
que retorna o que se alguma alteração na sua aparencia se fizer necessária, mensa-
ícone gens especificas para perfazer a alteração deverão ser enviadas.
A classe Menu como podemos ver é bem poderosa, mas criar
menus utilizando diretamente a mesma pode ser um tanto custoso pois
Texto de ajuda os passos para criação são longos e muito procedimentais. Desta forma
que será mostrado aconselhamos o leitor a navegar pelas classes Menu e MenuItem a
se você deixar o cursor
algum tempo em cima do menu título de conhecimento, mas quando for realmente criar seus menus, utili-
zar o menu editor apresentado anteriormente ou ainda a classe Menu-
Figura 15.7 Aba de propriedades Details do Menu Editor Builder que apresentaremos na próxima seção. A seguir
apresentaremos alguns exemplos de menu criados utilizando a classe
"criando um menu programaticamente (Menu)" Menu, a partir destes exemplos o leitor poderá ver que em verdade os
|menu| métodos tendem a ser grandes demais para menus complexos2.
menu := Menu labels: 'um\dois\três'
withCRs Como sabemos, um menu possui uma lista de instancias da A classe
lines: #(3). classe MenuItem que representam individualmente cada item do menu. MenuItem
menu startUp. A maioria das ações de alteração de propriedades aplicadas à um menu
Exemplo 15.1 Código para gerar dinamicamente um menu simples são implementadas por esta classe. A seguir podemos observar na

no menu. A variável groupSizes é um array de inteiros que contém,


em ordem de apresentação o número de ítens em cada grupo. 2. A mensagem ‘withCRs’ troca o caracter $\ por um enter.

290 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 291


Menus Criando um Menu Programaticamente

"exemplo de menu com valores de retorno" value: define o valor de retorno do item
|menu|
color retorna a cor do item
menu := Menu labels: color: define a cor do item
'circulo\esfera\quadrado\cubo' withCRs beOff deseleciona o item caso esteja selecionado
lines: #(4)
values: #('azul' 'verde' 'amarelo' 'laranja' ). beOn seleciona o item caso ele não esteja
hasindicator verifica se o item é do tipo checked
Transcript show: (menu startUp).
isOff verifica se o item esta deselecionado
Exemplo 15.2 Código para gerar dinamicamente um menu com valores de retorno
isOn verifica se o item esta selecionado
submenu retorna o submenu que o item representa
submenu: define o um submenu para o item
hasSubmenu verifica se o item tem um submenu
Tabela 15.1 Algumas mensagens para acesso e alteração de ítens de menu

Figura 15.8 Menu gerado pelo código do exemplo 15.2 A classe MenuBuilder tem como objetivo facilitar a criação de A classe
menus em relação a direta utilização da classe Menu. Ela provê métodos MenuBuilder
tabela 15.1 algumas mensagens úteis para perfazer alterações como
para a criação de menus item a item eliminando a necessidade de se
abilitar e desabilitar itens, checa-los, etc.
definir um array para labels e outro para valores como vimos no caso em
que criamos menus a partir da classe Menu, embora essa forma de cria-
Mensagem Função ção de menus seja também suportada.
enable abilita o item caso esteja desabilitado
Para criarmos um menu utilizando a classe MenuBuilder deve-
desable desabilita o item caso esteja habilitado mos primeiro criar uma instancia desta classe e em seguida enviarmos
isEnable retorna um booleano indicando se o item está habilitado mensagem para criação e configuração de itens e subitens de menu.

nameKey retorna o ID
nameKey: define um ID
position retorna a posição do item
label detorna o label do item
label: altera o label do item
Figura 15.9 Menu criado utilizando a classe MenuBuilder
value retorna o valor de retorno do item
Tabela 15.1 Algumas mensagens para acesso e alteração de ítens de menu O exemplo 15.3 cria o menu apresentado na figura 15.9 .

292 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 293


Menus Tipos de Menus

"exemplo" método descrição


|menu| add: este método pede como argumento um objeto tipo
associação que terá um lado da associação tomado
menu := MenuBuilder new. para ser o label do item e o outro como o valor de
retorno.
menu beginSubMenuLabeled: 'arquivo' ;
addLabel: 'editar' value: #mnuEditar; addLabel: value: este é o método mais simples de se utilizar. A palavra
addLabel: 'salvar' value: #mnuSalvar; chave addLabel: espera uma string que será utilizada
line; como label do item e value: espera qualquer objeto
addLabel: 'sair' value: #mnuSair; que será retornado quando o ítem for selecionado.
endSubMenu; addLabels:andValues: similar ao método utilizado pela classe Menu.
line; serve para criar submenus. reporte-se ao
beginSubMenuLabeled:
addLabel: '&Formatar' value: #mnuFormatar. exemplo14.3. pode ser utilizado de maneira aninhada
menu startUp endSubMenu finaliza um submenu
Exemplo 15.3 Construindo um menu utilizando recursos da classe MenuBuilder line inclui uma linha de separação entre os itens.
Tabela 14.2 Métodos para a criação de menus da classe MenuBuilder
Os métodos encontrados sob o protocolo building são utilizan-
dos para a criação de novos itens de menu e subitens, assim como |menu|
linhas de separação. A tabela 14.2 lista estes métodos e fornece uma
pequene explicação de suas funcionalidades. menu := MenuBuilder new.
No protocolo text menu patterns da classe MenuBuilder existem menu addFindReplaceUndo startUp
métodos que criam alguns menus padão. Vale dar uma navegada por Exemplo 15.4 Construindo um menu usando código para menus padronizados
este protocolo e testa-los. A seguir apresentamos um exemplo
Obviamente estes menus fornecidos não perfazer as ações que
eles listam, elas devem ser implementadas pelo programador.
A classe MenuBuilder ainda possui alguns exemplos que podem
ser encontrados no protocolo de classes examples. Estes exemplos
podem ser testados da maneira mostrada no exemplo 15.5. Figura 15.10 Menu produzido pelo código do exemplo 15.4

MenuBuilder example1 startUp


15.3 Tipos de Menus Exemplo 15.5 Menu-exemplo
Menus de uma forma geral são sempre instâncias da classe
Menu. Porém sua apresentação gráfica pode assumir 3 formas distindas.

294 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 295


Menus Tipos de Menus

Eles podem ser apresentados como barras de menu na parte superior de Menus popUp são utilizados exaustivamente por todo o ambi- Menus popUp
uma janela, também podem aparecem sob a forma de menus popUp e ente de desenvolvimento e são amplamente suportados pelos widgets
por último em forma de botões. para criação de GUIs. Em geral eles são definidos exatamente como
definimos barras de menu (visto no tópico anterior) porém caso o leitor
Barras de Barras de menu são apresentadas na parte superior das janelas. tenha alguma dúvida, reporte-se a bibliografia, ou ao help do Visu-
menu Elas são suportadas diretamente pelo canvas no UIPainter e podem ser alWorks, em geral o processo é bem simples.
adicionadas a janela através de sua janela de propriedades. A título de exemplo vamos criar uma janela e a ela adicionar
Na janela de propriedade existe um botão de checagem nome- uma caixa de listagem, em seguida tomaremos o exemplo14.3 e ligare-
ado enable, se ele estiver checado o campo menu será habilitado. mos o mesmo à caixa de listagem.
Nele devemos digitar o nome do recurso que implementa o menu. Para que o exemplo 14.3 possa ser utilizado deveremos modifi-
car sua última linha de código como é apresentado no exemplo 14.6.
Devemos então criar um método de instância sob um protocolo qualquer,
contendo o código para a criação do menu e por último definirmos a pro-
priedade menu da caixa de listagem com um simbolo igual ao nome
deste método.

^menu menu
Exemplo 15.6 Modificação do código

O método ‘menu’ que podemos ver no exemplo 14.6 retorna


uma instancia da classe Menu pois a caixa de listagem espera uma ins-
tancia desta classe e não de MenuBuilder. Nome que a primeira ocor-
rencia da palavra menu é uma variável temporária e a segunda o nome
de um método de instancia da classe MenuBuilder.
A figura 15.12 na página 298 apresenta a interface criada para o
exemplo. Para abrir o menu basta que se clique com o botão direito do
mouse sobre a caixa de listagem.

Botões de menu funcionam a semelança de uma caixa combo, Botões de


eles ficam fechados e quando clicamos sobre, eles se abrem. São muito menu
uitlizados em aplicações escreitas para internet e sua forma de definição
segue o padrão descrito anteriormente.
Figura 15.11 Definindo uma barra de menu

296 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 297


Menus Exercícios

Para acessar todo um submenu podemos inviar a mensagem


‘submenu’ a um item que implementa um submenu.
Agora que já sabemos como acessar menus, para alterarmo-nos
basta que utilizemos alguma das mensagens que alteram propriedades
vistas anteriormente.

15.5 Exercícios
1. Crie um menu contendo os seguintes items utilizando o menu editor:
arquivo editar ajuda
abrir recortar sobre
salvar colar
------- copiar
fechar desfazer
Figura 15.12 Exemplo de utilização de menu 2. Defina um símbolo de retorno para cada um dos itens deste menu.
3. Selecione algumas imagens e atribua-as a estes itens de menu.
4. Faça o mesmo sugerido nos exercícios 1 e 2 porém agora utilizando
15.4 Acessando Menus o MenuBuilder.
5. Crie uma janela e defina o menu priviamente criado como uma barra
Em muitos casos haverá a necessidade de se alterar um menu de menu.
dinâmicamente, para tal faz-se necessário um bom entendimento das
6. Adicione a janela criada no exercício anterior uma caixa de listagem e
classes Menu, MenuItem e, em alguns casos da classe MenuBuilder. O ligue o menu criado no exercício 1 a ela.
conhecimento básico sobre estas 3 classes já foi visto, agora resta-nos
explicar como fazer referência a menus.
Para menus criados através do menu editor devemos enviar a
mensagem ‘menuAt:’ para o builder, passando como argumento um
símbolo identico ao nome do recurso que implementa o menu. A retorno
desta mensagem será uma referência ao menu que desejamos acessar.
Já de posse de uma referência ao menu podemos então acessar
seus ítens através do envio das mensagens ‘menuItemLabeled:’ ou
‘atNameKey:’. estas mensagens esperam como argumentos o label do
item ou o ID do mesmo, respectivamente.

298 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 299


Menus

Capítulo 16 2SDUDGLJPD09&
0RGHO9LHZ&RQWUROOHU

Neste capítulo você vai aprender como funciona um conceito


básico para interação entre aplicações e suas interfaces utilizado por lin-
guagens de programação legitimamente orientadas a objetos: o paradigma
MVC. Ao final do capítulo, você vai aprender a conectar uma aplicação (o
modelo) com sua representação (o view) e com o processo que controla
sua interface (o controller) utilizando recursos do mecanismo de depen-
dência já vistos.

16.1 O que é MVC ?


O VisualWorks, bem como todas as implementações do Smalltalk
que seguem a versão Smalltalk-80 da XEROX-PARC imcorporam uma
estratégia chamada MVC (Model View Controller) para a criação de aplica-
ções com interfaces gráficas. A linguagem JAVA também incorporou uma
variante do paradigma MVC na sua forma de implementar interfaces de
usuário.
Um dos grandes problemas na criação de aplicações era a
extrema dependência que existia entre o processamento específico da

300 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


O paradigma MVC (Model-View-Controller) O que é MVC ?

aplicação e os mecanismos que se responsabilizavam pela apresenta-


ção das imformações produzidas na tela e pela captura e tratamento das Processamento
entradas do usuário. da aplicação
Um programador chamado Trygve Reenskang desenvolveu uma
estratégia de programação para este tipo de aplicação onde existiam três
camadas bem definidas e separadas.
Model
A primeira se destinava a conter todas as estruturas, informa-
ções e procedimentos necessários para implemtar o funcionamento da Captura e tratamento
Responsável pela
aplicação, porém sem se preocupar com como a informação produzida das entradas do
apresentação das deped.
seria apresentada ao usuário. A esta camada deu-se o nome de MODEL. usuário
informações ao usuário
A segunda se destinava unicamente a apresentar as informações produ- ref. ref.
zidas pelo modelo na tela. A esta camada deu-se o nome de VIEW. Esta
segunda camada se responsabilizava por definir toda a estratégia de
ref.
apresentação, fosse ela em forma de texto, de componentes gráficos tais
como botões de todos os tipos imagináveis, listas e também imagens,
geralmente matrizes de pixels (os famosos bitmaps). View Controller

A terceira era projetada para capturar e gerenciar toda a entrada


ref
de dados executada pelo usuário. Geralmente as ações inirentes ao
mouse, tais como movimentos, botões precionados e segurados, e tam-
Figura 16.1 Arquitetura MVC
bém as ações do teclado. A esta camada deu-se o nome de CONTROL-
LER. Otra vantágem é a reusabilidade do código desenvolvido. Por
Com este modelo definido por partes completamente indepen- exemplo pode-se cirar um MODEL e ele ser usado por duas interfaces
dentes entre si, restava a tarefa de se definir um mecanismo de comuni- completamente distintas.
cação entre as partes. O mecanismo adotado foi o esquema de Esta metodologia de programação então foi adotada como
dependência entre objetos visto no capítulo 9. Também se criou algumas padrão para a criação do ambiente de desenvolvimento do Smalltalk,
referências entre os objetos do modelo (visto mais à frente) para facilitar bem como para a criação de qualquer aplicação dentro do ambiente.
o acesso as informações inerentes a cada um. Tudo que existe no Smalltalk onde se observa processamento, apresen-
As vantágens inerentes a esta metodologia de programação são tam-se infromações e gerencia-se a entrada do usuário, é uma aplicação
várias. Dentre elas podemos observar que a modularidade fornecida pela desenvolvida sobre esta metodologia. Podemos citar como exemplo todo
separação entre as 3 camadas permitem que vários programadores tra- o ambiente de desenvolvimento do VisualWorks, como o SystemBrow-
balhem me saparado em cada um dos componentes sem se preocupar ser, o Laucher, o WorkSpace e assim por diante.
como a integração das mesmas, pois esta se dará de forma natural.

302 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 303


O paradigma MVC (Model-View-Controller) Model

16.2 Model
Model
O MODEL se responsabiliza por todo o rocessamento inerente a
aplicação em específico. Nele devem estar contidos todos os algorítmos,
procedimentos, tarefas para a mudança do estado da aplicação. Por
exemplo, em uma ferramenta de busca de substrings dentro de um texto,
o MODEL da aplicação se responsabilizaria pelo algorítmo de busca da ValueModel
substring. Uma vez encontrada a substring a tarefa do MODEL está fin-
dada restando apenas a sinalizxação do final do trabalho. O retorno do
resultado da pesquisa então fica sobre a responsabilidade do VIEW.
ValueHolder
Hierarquia de O model de uma aplicação pode ser extremamente simples
classes como por exemplo uma string, ou pode ser complexo ao extremo, como
por exemplo todo um conjunto de objetos para a criação e formatação de
páginas em HTML. O MODEL usualmente é um único objeto e sua com- PluggableAdaptor
plexidade rezide no fato dele poder ser composto por outros tantos obje-
tos.
Então dizemos que um MODEL deve possuir duas caracteríscti-
ApplicationModel
cas básicas:
• Possuir a capacidade de reter referêcias aos seus dependentes
• Prover todo o processamento necessário para o funcionamento Figura 16.2 Hierarquia de classes de Model
da aplicação
instância. Isso torna mais rápido a notificação dos dependentes, porém
A classe A classe Model é subclasse de Object e tem como função imple- acarreta uma maior utilização de espaço.
Model mentar um mecanismo para pesquisa de dependentes mais rápido que o Outras características específicas ao Model são adicionadas em
provido pela classe Object. Na classe object os dependentes são regis- suas muitas subclasses, porém tenha em mente que um objeto direta-
trados em um único didionário que é uma variável estática a classe. A mente filho de Object pode ser utilizado como Model de sua aplicação.
medida que o número de dependentes de várias aplicações vão sendo devemos apenas ter em mente que esta não é a melhor maneira.
adicionados, este dicionário tente a crescer de tamanho o que acarreta Existem várias classes que podemos utilizar como base para o
uma demota considerada na tarefa de pesquisar e informar os depen- modelo de nossa aplicação. A hierarquia de classes que se controe sob a
dentes de uma alteração ocorrida no onbjeto. Em vez de manter apenas classe Model fornece uma gama bem variada de opções com várias
um dicionário, a classe Model mantem seus dependentes em uma variá- características distintas. Em geral utilizamos a classe Model quando
vel de instancia (dependents) que apenas contém os dependentes da nenhuma de suas classes especializadas

304 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 305


O paradigma MVC (Model-View-Controller) View

ValueModel e Anteriormente dissemos que quaisquer objetos, tais como


suas strings e números poderiam ser utilizados como Models das nossas apli- 16.3 View
subclasses cações. Como todo objeto necessariamente é filho de Object isso não Como foi dito anteriormente, o View é a interface da aplicação.
deixa de ser verdade. Porém se assim procedessemos fazendo uma Nas implementações mais antigas do Smalltalk a classe View e suas
string sendo model de uma aplicação cairíamos no problema da lentidão subclasses já possuiam a capacidade de se apresentarem na tela. Com
da notificação dos seus dependentes. Para suprir esta deficiência, a o avanço dos sistemas operacionais orientados a janelas e com a cres-
classe Model possui uma subclasse abstrata chamada ValueModel. Ins- cente necessidade de tornar o Smalltalk portável para várias platafor-
tâncias da classe ValueModel. Ela provê o mecanismo necessário para mas, a estratégia adotada foi criar uma parte da hierarquia de classes
informar seus dependentes de alterações ocorridas em seu estado. Ela específica para gerenciar a comunicação com o sistema operacional e
também define os métodos abstratos que devem ser implementados em fazer uso das primitivas de janelas da própria máquina, ganhando assim
suas subclasses. performance e maleabilidade.
A classe ValueHolder é a mais simples de todas as suas sub- Em resumo, a saida gráfica mais externa sempre será uma
classes. Ela possui uma única variável de instancia chamada value que janela. Uma janela pode ter apenas um componente dentro dela. A estra-
retém um objeto. Esta classe foi desenhada para conter qualquer objeto tégia adotada para que dentro de uma mesma janela possamos ter
e por isso na classe Object existe uma mensagem de converção que per- vários componentes é compo-la com uma série de objetos que geren-
mite converter qualquer objeto em um ValueHolder. ciem esta manipulação. A aparencia da janela pode ser definida pelo
Além da possibilidade de se converter qualquer objeto direta- Layout dela e ele poderá ser uma instancia da classe Layout. Desde a
mente para um ValueHolder através da mensagem asValue, ainda exis- implementação original do Smalltalk-80 até a atual versão 5i.3 do Visu-
tem muitas formas de se criar um novo ValueHolder. Podemos, por alWorks esta é provavelmente a parte que mais mudou na hierarquia de
exemplo: classes. Também é a parte mais complicada de se entender do Smalltalk.

ValueHolder with: qualquerObjeto


16.4 Controller
ValueHolder newBoolean
ValueHolder newString A última das três partes do paradigma MVC, porém não menos
ValueHolder newFraction importante é o Controller. Ele se responsabiliza por gerenciar toda a inte-
Exemplo 15.1 Maneiras de se crar um ValueHolder reção do usuário com a aplicação. Geralemente ele se resposabiliza pela
captura de enventos do mouse, tais como botões prescionados, soltos ou
Existem ainda muitas outras subclasses de ValueModel especi- segurados, além perceber tmabém os movimentos do mouse. Quanto ao
alizadas para vários propósitos específicos. teclado, o controller se responsabiliza por capturar todas as teclas, bem
como as combinações possíveis das teclas especiais.
Geralmente, a maneira como a entrada será tratada por uma
aplicação é muito particular a aplicação propriamente dita. Por este
motivo observamos que o controller da aplicação é a parte menos sucetí-

306 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 307


O paradigma MVC (Model-View-Controller) Controller

vel a reutilização. Também este é o fato pelo qual temos poucos compor-
tamentos genéricos implementados nas classes que geralemente
utilizamos como controllers de nossas aplicações. Controller

Hierarquia de Adiante apresentamos uma parte da hierarquia de classes dos


classes controllers. A classe Controller é uma classe abstrata de propósito geral
dentro do contexto de captura da entrada do usuário. Utilizamo-na geral-
mente quando não existe nenhuma de suas classes especializadas que ControllerWithMenu
tenham os serviços desejados já implementados. Utilize esta classe
como base do controller de sua aplicação apenas quando nenhuma outra
lhe servir. A classe ControllerWithMenu inclui a facilidade de associar um
menu popUp ao botão direito do mouse (yellow button). A classe NoCon- NoController
troller tem como única função nunca receber as entradas do usuário. Ela
é utilizada quando desejamos criar view’s estáticos, ou seja, quando
desejamos apenas apresentar informações ao usuário, sem fornecer a
possibilidade de intereção. A classe MenuController inclui uma grande
MenuController
variedade de facilidade para enteração com menus (visto que de certa
forma eles também podem ser considerados uma entrada direta do usuá-
rio). Por último temos a classes StandardSystemMenu que é utilizada
como controllers em instanicas da classes ScheduledWindow. Ele for-
nece toda a funcionalidade básica para manipulação de janelas, tais StandardSystemController
como minimizar, maximizar, menu de operação, etc. Muito dificilmente
você utilizará diretamente uma inmstancia desta classe.
A hierarquia de classes de controllers ainda é muito extensa e Figura 16.3 Hierarquia de classes de Controller
com vários níveis de especialização. Uma boa prática seria navegar por
elas e ler seus comentários para entender e aprendenr melhor as peculi- Ao contrário do que acontece com os Views, onde vários deles Mecanismo
aridades de cada uma destas classes. podem estar atualizando suas interfaces concorrentemente, para control- de obtenção
lers existe uma regrá básica. A entrada do usuário é única, e somente do controle
A classe Controller bem como todas as suas subclasses pos-
suem três variáveis de instancia, model, view e sensor. Respectiva- um dentre todos os controllers agendados no sistema poderá estar hou-
mente, uma referencia para o modelo da aplicação, uma referencia para vindo a entrada por vez.
a interface da aplicação e uma referencia aos dispositivos de entrada Para que esta regra seja respeitada, faz-se necessário então um
(mouse e teclado). Geralmente a variável de instancia sensor, armazena arbitro para definir qual dentre todos os controllers agendados terá o con-
uma instância da classe InputSensor que será vista mais a frente. trole sobre a entrada do usuário.

308 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 309


O paradigma MVC (Model-View-Controller) Receita

Convenções Aqui vai uma nota histórica sobre o Smalltalk mais que poderá 3. Não se preocupe em que pontos do modelo da aplicação os depen-
do mouse ser de grande utilizada a você durante as suas navegadas pela biblioteca dentes deverão ser informados das alterações no estado do modelo,
de classes do VisualWorks. deixe isto para mais a frente,
4. Teste sua aplicação através do Workspace e do Transcript. Este
Por razões históricas foi associado uma cor a cada botão do
passo é opcional, porém tente não pulá-lo pois é um ótimo momento
mouse.
para encontrar erros na estrutura de sua aplicação e nos algorítmos
O botão da esquerda, também conhecido como botão de sele- que ela contém.
ção e chamado de red button. 5. Construa a interface da aplicação, ou seja, crie as suas classes Views
O botão do meio, também conhecido como botão de operação e filhas de alguma das classes encontradas na biblioteca de classes.
Se você não encontrar nenhuma que se adeque a sua aplicação, uti-
chamado de yellow button.
lize a classe View por ser a mais genérica.
O botão da direita, também conhecido como botão das opera- 6. Adicione o seu view previamente criado a uma janela, usualmente a
ções da janela e chamado de blue button. uma instancia da classe ScheduledWindow. Lembre-se que é impera-
Press - prencionado e segurado. tivo que seu view esteja contido em uma janela, pois elas são a
maneira padrão de saída gráfica dentro do VisualWorks.
release - quando um botao e solto 7. Defina o layout da aplicação utilizando as técnicas de posicionamento
click - presciona e solta sem mover o mouse vistas no capítulo sobre janelas.
double-click - clica o botao duas vezes sem mover o mouse. 8. Crie os controllers para gerenciar a entrada do usuário. Lembre-se
que cada view deve possuir seu próprio controller. Escolha dentre os
disponíveis na biblioteca de classes. Se nenhum das classes se
encaixarem escolha a classes mais genérica Controller. Se o view ao
16.5 Receita qual o controller fizer par for passivo defina o controller como uma
instancia da classe NoController.
Aqui vamos apresentar uma pequena receita para a criação de
9. Teste a interface instanciando-a e inspecionando-a para verificar se
aplicações em Smalltalk utilizando o mecanismo MVC. Note que o que
todos os controllers estão corretos e para verificar também se o
apresentaremos aqui não e de forma nenhuma uma série de passos rig-
layout da interface está correto.
dos para serem seguidos e sim apenas uma maneira de cadenciar a
10.Defina os tratamentos das entradas do usuário nas classes Control-
construção de suas aplicações. Os passos seguintes visam diminuir o
ler.
tempo de desenvolvimento e facilitar a criação rápida de um protótipo de
11.Por último defina em que pontos do modelo da aplicação mensagens
suas aplicações.
de alteração do estado interno devem ser passadas aos dependen-
1. Comece pelo domínio da sua aplicação. Escolha a superclasse de tes.
sua aplicação com base nas funcionalidades já implementadas na 12.Teste, e refine o programa.
biblioteca de classes que se encaixem com o seu problema. Se
nenhuma das classes lhe parecer útil, utilize a classe Model.
Neste capítulo apresentamos toda a fundamentação teórica por Onde
2. Se o domínio de sua aplicação for coposto por várias classes, faça-as
traz do modelo MVC. De posse deste conhecimento, veremos no pró- encontrar
todos como instancias da sua classe principal (como definido anteri-
ximo capítulo uma aplicação simples para a criação interativa de um trei- exemplos ?
ormente).

310 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 311


O paradigma MVC (Model-View-Controller)

&RQVWUXLQGRXPD
nador de neurônios artificiais. O seguinte capítulo está organizado em
forma de um tutorial e foi escrito visando revisar a maioria dos conceitos Capítulo 17
discutidos durante todo o livro.

$SOLFDomR6LPXODGRU
GH5HGHV1HXUDLV

Neste tutorial vamos revisar os principais conceitos da linguagem


bem como apresentar um exemplo concreto da utilização do paradigma
MVC.BConstruiremos um programa extremamente simples para a simula-
ção de Redes Neurais. Mostraremos as facilidades e peculiaridades do
Smalltalk para o desenvolvimento de aplicações para Inteligência Artificial.
A idéia por trás deste tutorial é fugir dos exemplos superficiais. Textos téc-
nicos normalmente apresentam exemplos superficiais que não respondem
as dúvidas de um programador que geralmente remontam sobre aspectos
mais avançado da linguagem. Note que a intenção deste tutorial não é ser
uma referência em Inteligência Artificial. Apenas utilizamos o assunto para
exemplificar os conceitos e peculiaridades da linguagem Smalltalk e relaci-
onar o assunto com a facilidade que o Smalltalk o resolve.

17.1 Um Pouco de Teoria: Perceptrons


Para que possamos dar início ao desenvolvimento de nossa apli-
cação sobre treinamento de redes neuronais baseadas no modelo Percep-
tron, faremos uma brevíssima introdução ao assunto. Uma explicação

312 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Construindo uma Aplicação: Simulador de Redes Neurais Fundamentação Matemática

mais detalhada pode ser encontrada em qualquer livro sobre inteligência


artificial. 17.2 Fundamentação Matemática
Em 1959 Rosemblatt introduziu o conceito de Perceptron. Ele O perceptron é um interpolador. Ele ajusta seus pesos para que
nada mais era do que um modelo matemático, baseado nas pesquisas dependendo das suas entradas forneça a saída desejada. O modelo se
anteriores de Hebb, sobre um modelo que imitasse um neurônio bioló- baseia em uma função de ativação tipo a função degrau. Se a combina-
gico. Logo após a sua introdução este modelo foi utilizado com sucesso ção das entradas multiplicadas pelos seus respectivos pesos for menor
para a classificação de letras maiúsculas do alfabeto e também para o ou igual a um valor de ativação que aqui chamamos de bias a saída será
aprendizado de funções lógicas tais como a função E, OU, e Não. Um inibitória, caso contrário ela será excitatória.
dos primeiros conceitos de inteligência artificial conexcionista e também
 1, Σxi*wi – θ > 0
α=  
o mais simples.
 
O modelo é simples. Ele possui n entradas cada uma com um  0, Σxi*wi – θ ≤ 0
peso de influência, um valor de ativação, uma função de ativação e uma
saída. Caso a soma ponderada das entradas pelos seus pesos for menor Onde:
que o valor de ativação, um sinal inibitório é enviado para a saída, caso saída
contrário um sinal excitatório é enviado.
bias, ou valor de ativação
w peso da entrada
x entrada
net wi*xi

+1

0
net
Figura 17.1 Modelo computacional do neurônio de Hebb
Figura 17.2 Função de ativação em degrau ou limiar
Este modelo tem o seguinte problema, ele consegue apenas
classificar apenas problemas bem simples, ou como são conhecidos,
O algorítmo para o treino do Perceptron se dá em quatro passos Algoritmo do
problemas linearmente separáveis. Se Estruturássemos vários destes
básicos: Perceptron
Perceptrons em camadas eles resolveriam este problema, mais nestes
casos não existe um algoritmo para aprendizado automático. Um modelo 1. inicializar os pesos das entradas aleatoriamente (variamos entre o
mais completo é o Multilayer Perceptron que resolve este problema. valor 0 e o valor 1)

314 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 315


Construindo uma Aplicação: Simulador de Redes Neurais Criação da Classe NeuronioArtificial

2. selecionar um entre os vetores de entrada do conjunto de exemplo e


propagá-lo. NeuronioArtificial
3. se a resposta for errada, ajustar os pesos
4. voltar ao passo 2 enquanto ocorrerem respostas erradas
O ajuste dos pesos se dá pela regra de Windrow-Hoff. Sem Perceptron MLP
entrarmos em muitos detalhes ela e a seguinte:
Figura 17.3 Hirarquia de classes com uma classe NeurônioArtificial como classe abstrata.

∆wij = α ( β*xij ) Para criar a classe NeuronioArtificial selecionamos no System


Browser a categoria Aplicações do Livro no category view e acionamos o
menu Class->>Add class>>Fixed size. Um novo template para criação
de classes será mostrado no Code View. Preencha ele como segue.
17.3 Criação da Classe NeuronioArtificial
Smalltalk.InteligenciaArtificial defineClass: #NeuronioArtificial
O primeiro passo para a criação da nossa aplicação é definir
superclass: #{Core.Object}
uma superclasse abstrata que conterá as características mais comuns indexedType: #none
de todos os tipos de neuronios artificiais. Chamaremos ela de Neuronio- private: false
Artificial. instanceVariableNames: 'pesos entradas saida alpha '
classInstanceVariableNames: ''
Modelando Superclasses abstratas são classes com uma ou mais subclas- imports: ''
uma classe ses que não possuem funcionalidade suficiente para criar instancias category: 'Aplicacoes Perceptron'
abstrata úteis. Sua função é agrupar características comuns as suas subclasses. Exemplo 17.1 Declaração da classe NeuronioArtificial
Em nossa aplicação-exemplo começaremos introduzindo uma
classe abstrata chamada NeuronioArtificial, que conterá as característi- Agora que nossa classe NeuronioAritficial Está definida vamos Criando
cas básicas pertinentes a todos os tipos de neuronios artificiais. Depois incluir seus métodos de classe. Métodos de classe são métodos que construtores
criaremos a classe Perceptron, subclasse de NeuronioArtificial que é o implementam mensagens entendidas pela classe e não pelas suas ins-
tipo mais simples dos que aqui usaremos. Em seguida criaremos o tancias.
modelo da nossa aplicação, a classe que se responsabilizará pelo treino Adicione o protocolo instance creation. Sob este protocolo
do nosso Perceptron, um controller para capturarmos as entradas e normalmente ficam agrupados os métodos para criação de novas instân-
acessar-mos um menu e finalmente um view para a apresentação de cias, que em algumas linguagens de programação, como C++, recebem
informações finalizando assim a nossa aplicação. Mostraremos como o nome de construtores.
avaliá-la e por fim apresentaremos uma maneira simples de mostrar gra- Criemos a método new: que se responsabilizará pela criação de
ficamente o resultado do treino. Caso você não tenha conhecimentos de uma nova instância da classe NeuronioArtificial já com o exato número
IA, não se preocupe, o embasamento teórico para entender esta aplica- de entradas desejadas.
ção é mínimo e você vai compreendê-lo num instante.

316 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 317


Construindo uma Aplicação: Simulador de Redes Neurais Criação da Classe NeuronioArtificial

Para criar o método, basta que se selecione o protocolo recente- alpha


mente criado, e um template para a criação de métodos será mostrado “método que retorna o atual alpha “
no Code view. Delete o template e adicione o código do exemplo 17.2. ^alpha

new: numEntradas “*********************************“


alpha: novoAlpha
^super new initialize: numEntradas “Método que altera a alpha desde que ele esteja na faixa
Exemplo 17.2 Método de classe para criação de instâncias estipulada
A faixa é definida por números reais entre 0 e 1“
Note que este método executa a mensagem de criação de intan-
cias de sua superclasse (no caso Object). Isto faz com que o objeto seja (noovAlpha >= 0 & novoAlpha <=1) ifFalse:[
corretamente criado com todos os mecanismos e características do for- Dialog warn: 'O valor do alpha deve \estar entre zero e um.'
necidos pela sua superclasse. withCRs.
] ifTrue:[
Utilizando o mecanismo de encadeamento de mensagem cha- alpha := novoAlpha.
mamos a mensagem initialize que se responsabilizará por inicializar cor- ].
retamente os atributos de nosso objeto.
“**********************************“
Criando Agora passemos a inclusão dos métodos de instância. Métodos fornecaSaida
métodos de de instância são métodos que só podem ser executados por instancias “Método que retorna o valor de saída “
instância de uma determinada classe. Sob o protocolo private adicionemos o
^self subclassResponsibility
método do exemplo 3. esta chamada da mensagem subclassRespon-
“**********************************“
sibility é uma características da prototipação de classes abstratas.
numEntradas
Isto significa que se este método tentar ser acessado, uma exceção "responde um inteiro representando o numero de entradas"
ocorrerá informando que este método deverá ser sobrescrito por uma de
suas classes filhas. Chamamos a estes de métodos abstratos, que são ^pesos size
métodos que são prototipados em uma classe abstrata e devem ser Exemplo 17.3 Métodos agrupados sob o protocolo accessing
reescritos nas subclasses.
Agora incluiremos os métodos de acesso a informações referen- abstrata está no fato de sabermos que as subclasses deverão possuir
tes ao objeto. Normalmente todos os métodos que informam ou alteram este método, mais a sua implementação é específica para cada tipo de
o estado de um objeto, são agrupados sobre o protocolo acessing. NeuronioArtificial. Esta prática torna seus objetos bem estruturados e
facilita a depuração de erro além de aumentar a reusabilidade.
Os próximos três métodos devem ficar sob o protocolo proces-
sing. Todos são métodos abstratos que devem ser implementados pelas
Sob o protocolo initialize-release agrupamos todos os métodos Organizando
subclasses de NeuronioArtificial. O motivo pelo qual definimos vários protocolos de
que tem por incumbência inicializar algum aspecto do estado interno de
métodos que são de responsabilidade das subclasses em uma classe métodos
nosso objeto, e também os métodos responsáveis pela liberação destes

318 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 319


Construindo uma Aplicação: Simulador de Redes Neurais Criação da Classe Perceptron

ajustePesos: umExemplo saida: umaSaida iniciaPesos: numEntradas


^self subclassResponsibility "Inicia os pesos iniciais. Por definicao seta valores entre 0 e
“**********************************“ 1"
calculeErro
^self subclassResponsibility numEntradas timesRepeat:[
“**********************************“ pesos add: Random new next rounded.
calculeNet: umConjDeEntrada ].
^self subclassResponsibility
Exemplo 17.4 Métodos abstratos “**********************************“
initialize: numEntradas
objetos. Protocolos são muito úteis na organização dos métodos. Tente "inicia as principais propriedades do neurônio artificial”
utilizar em suas classes os mesmos protocolos da biblioteca de classes.
Isso manterá a convenção e facilitará outras pessoas a entender suas "inicia coleção de pesos"
classes. pesos := OrderedCollection new.
self iniciaPesos: numEntradas.
Terminada a inclusão dos métodos acima, temos a nossa classe
NeuronioArtificial completa. Note como foi simples a criação da mesma, "inicia a taxa de aprendizado. Por definicao começa com 1"
e como foi necessário pouco código para a sua criação. Também não alpha := 1.
desobedecemos a convenção que dita que todos os métodos devem ter Exemplo 17.5 métodos para inicialização dos atributos da classes
seu tamanho girando em torno de 7 linhas.
Métodos para a liberação de objetos só são necessários em Smalltalk.InteligenciaArtificial defineClass: #Perceptron
casos especiais pois, como sabemos, o Smalltalk é equipado com um superclass: #{InteligenciaArtificial.NeuronioArtificial}
coletor de lixo. Os motivos pelos quais um objeto devem ser explicita- indexedType: #none
mente liberados podem ser encontrados no capítulo que se refere a private: false
instanceVariableNames: 'bias pesoBias '
mecanismos de dependência.
classInstanceVariableNames: ''
imports: ''
category: 'Aplicacoes do Livro'
17.4 Criação da Classe Perceptron Exemplo 17.6 template para a criação da classe Perceptron
Passaremos agorea à criação da classe Perceptron, que é um
Sob o protocolo de classe instance creation, inclua a método a
tipo especializado de NeuronioArtificial e que será subclasse do mesmo.
seguir.
Abaixo mostramos o template para a criação da classe Percep-
tron. Proceda exatamente da mesma maneira que você fez para a cria- new: numEntradas
ção da classe NeuronioArtificial. Note que no campo superclass, a classe ^super new:numEntradas.
indicada é NeuronioArtificial, isso faz com que a classe Perceptron seja Exemplo 17.7 Método para criação de instancias
sua subclasse.

320 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 321


Construindo uma Aplicação: Simulador de Redes Neurais Criação da Classe Perceptron

Sob o protocolo de instância accessing inclua os seguintes Sob o protocolo de infância processing, adicione os métodos
métodos. Note que aqui redefinimos o método fornecaSaida: que era de que seguem. Note que aqui estão redefinidos vários dos métodos que
responsabilidade da subclasse. eram de responsabilidade das subclasses de NeuronioArtificia.l

bias: novoBias funcaoAtivacao: arg


bias := novoBias.
(arg <= 0) ifTrue:[^-1] ifFalse:[^1].
“********************************“
fornecaSaida: umConjDeEntrada Exemplo 17.10 função de ativação degrau
"Responde a um conjunto de entrada"
^self funcaoAtivacao: (self calculeNet: umConjDeEntrada).

Exemplo 17.8 métodos de acesso ao estado do objeto

Sob o protocolo de instância initialize-release, inclua os seguin-


tes métodos. Observe que no método initialize: utilizamos uma outra
maneira de se inicializar o objeto pai NeuronioArtificial.

iniciaPesoBias
"Inicia aleatoriamente o peso do bias, valor entre 0 e 1"

pesoBias :=Random new next rounded.

“********************************“
initialize: numEntradas
"inicia informações sobre o perceptron"

super initialize: numEntradas.

"inicia o valor do bias"


bias := -1.

"inicializa o peso do bias"


self iniciaPesoBias.
Exemplo 17.9 métodos para inicialização do estado interno do objeto

322 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 323


Construindo uma Aplicação: Simulador de Redes Neurais Criação do Modelo de Domínio para a Aplicação (ModeloPerceptron)

Sob o protocolo de instância private adicione o seguinte método.


Note que aqui redefinimos o método que representa a função de ativação 17.5 Criação do Modelo de Domínio para a
adotada para este tipo de NeuronioArtificial. Aplicação (ModeloPerceptron)
Tipicamente uma aplicação em Smalltalk é composta por duas
ajustePesos: umExemplo saida: umaSaida
partes bem separadas. São elas o domínio da aplicação e a interface
"atualiza os pesos das coneccoes e do bias"
com o usuário. A classe ModeloPerceptron se destina a cobrir a tarefa
self atualizaPesoBias: umExemplo saida: umaSaida. do domínio da aplicação.
self atualizaPesosEntradas: umExemplo saida: umaSaida. Faremos com que a classe ModeloPerceptron seja subclasse de
Model. Isso fornecerá a nossa aplicação a funcionalidade de comunica-
“********************************“ ção com a interface com o usuário que será descrita mais a diante.
atualizaPesoBias: umExemplo saida: umaSaida
"atualiza o peso do bias"
Smalltalk.InteligenciaArtificial defineClass: #ModeloPerceptron
superclass: #{UI.Model}
pesoBias := pesoBias + (alpha * umaSaida * bias).
indexedType: #none
private: false
“********************************“
instanceVariableNames: 'numEpocas conjDeTreinamento perceptron
atualizaPesosEntradas: umExemplo saida: umaSaida
conjSaidas '
"atualiza os pesos das coneccoes "
classInstanceVariableNames: ''
imports: ''
1 to: (self numEntradas) do:[:cont| |pesoAntigo|
category: 'Aplicacoes Perceptron'
pesoAntigo := pesos at: cont.
pesos at: cont put: (pesoAntigo + (alpha * (umExemplo at: Exemplo 17.11 Template para a criação da classe ModeloPerceptron
cont) * umaSaida)).
Uma vez definida a classe vamos começar a incluir seus méto-
].
dos que executarão o processamento referente a aplicação. A primeira
“********************************“ coisa a fazer é definir o método de criação de instancias. Ele deve estar
calculeNet: umConjDeEntrada agrupado sobre o protocolo de classe instance creation.
"Calcula o net contendo o bias"
new: numEntradas conjDeTreinamento: umConjDeTreino
saida := 0. saidasDesejadas: conjSaidas
1 to: (self numEntradas) do:[: cont|
saida := saida + ((pesos at: cont) * (umConjDeEntrada at: ^super new initialize: numEntradas conjDeTreinamento:
cont)). umConjDeTreino saidasDesejadas: conjSaidas.
]. Exemplo 17.12 Método de classe para a criação de instancias
^saida := saida + (bias * pesoBias).
Figura 5.4 mensagens do protocolo processing

324 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 325


Construindo uma Aplicação: Simulador de Redes Neurais Criação do Modelo de Domínio para a Aplicação (ModeloPerceptron)

Sob o protocolo de instância initialize-release adicione o que provê um comportamento padrão para comunicação entre o objeto e
seguinte método que se responsabilizará pela correta inicialização de a janela. A este tipo especial de objeto damos o nome de wrapper1.
todos os atributos da classe. A Classe ScheduledWindow é um dos 3 tipos de superfícies grá-
ficas suportadas pelo VisualWorks. Além dela ainda temos Pixmap e
initialize: numEntradas conjDeTreinamento: umConjDeTreino Mask. Objetos gráficos só podem ser apresentados sobre uma superfí-
saidasDesejadas: conjDeSaidas cies gráfica. ScheduledWindow éum tipo especial de janela. Possui um
numEpocas := 0.
controller que fornece as funcionalidades esperadas de uma janela, tais
conjDeTreinamento := umConjDeTreino.
como movê-la e redimensioná-la.
conjSaidas := conjDeSaidas.
perceptron := Perceptron new: numEntradas .
Exemplo 17.13 Método que inicializa o estado interno do objeto
alteraAlpha
|novoAlpha|
O seguinte método cria uma janela adiciona o view a ela e apre- novoAlpha := Dialog request: 'Preencha o campo com um novo
senta a mesma na tela. Deixe para incluir este método após criar as clas- alpha'.
self perceptron alpha: (novoAlpha asNumber).
ses PerceptronView e PerceptronController, pois ao aceitar o seguinte
conjDeTreinamento
método, o compilador irá reclamar devido ao fato das referidas classes
^conjDeTreinamento.
ainda não existirem. conjSaidas
^conjSaidas.
open numEpocas
"cria uma janela e adiciona " ^numEpocas.
| wrapper window percView| perceptron
window := ScheduledWindow ^perceptron
model: self Exemplo 17.15 Métodos de acesso do perceptron
label: 'Inspertor do perceptron'
minimumSize: 350@250.
percView := PerceptronView new.
percView model: self.
wrapper := BorderedWrapper on: percView.
wrapper insideColor: ColorValue white.
wrapper borderWidth: 3.
percView controller: PerceptronController new.
window component: wrapper.
window open.
Exemplo 17.14 método para a criação e abertura de uma janela

Como existem muitos objetos que podem servir como compo-


nentes em uma janela, os “empacotamos“ em um tipo especial de objeto 1. Embrulho

326 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 327


Construindo uma Aplicação: Simulador de Redes Neurais Testanto o Funcionamento

O seguinte método implementa o algorítmo de treinamento de


neuronios artificiais tipo perceptron. Ele é baseado na fundamentação 17.6 Testanto o Funcionamento
teórica apresentada aqui neste capítulo. Agora que já temos suficiente código criado, podemos testar o
funcionamento do nosso programa. Para tal utilizaremos o Workspace
treine fornecido pelo VisualWorks.Definamos um conjunto de treinamento um
"Aplica a algoritmo de treinamento baseado na regra de Hebb conjunto de saídas desejadas e vejamos o que acontece.
vewrificar a correcao"
|noAjustes| Uma boa maneira de testar o funcionamento de nossas aplica-
ções e criar objetos no workspace e apresentar as saídas no System
numEpocas := 0. Transcript

[noAjustes := 0. "treinamento da funcao logica and"


1 to: (conjDeTreinamento size) do:[:pos| |saida| ModeloPerc := ModeloPerceptron new: 2 conjDeTreinamento: (#(#(-1 -
saida := perceptron fornecaSaida: (conjDeTreinamento 1) #(-1 1) #(1 -1) #(1 1)) asOrderedCollection) saidasDesejadas:
at:pos). (#(-1 -1 -1 1) asOrderedCollection).
(saida == (conjSaidas at: pos)) ifFalse:[
perceptron ajustePesos: (conjDeTreinamento at: pos) ModeloPerc treine.
saida: (conjSaidas at: pos). Perc := ModeloPerc perceptron.
noAjustes := noAjustes + 1 Smalltalk.Root basicInspect
] Transcript show: (Perc fornecaSaida: #(-1 -1)) printString.
] Transcript show: (Perc fornecaSaida: #(-1 1)) printString.
numEpocas := numEpocas + 1. Transcript show: (Perc fornecaSaida: #(1 -1)) printString.
noAjustes == 0] whileFalse. Transcript show: (Perc fornecaSaida: #(1 1)) printString.
Exemplo 17.17 Código para teste da aplicação
self changed: #fimTreino with: nil.
Exemplo 17.16 Algorítmo de aprendizado do perceptron Ao avaliarmos o código acima, o VisualWorks nos declarará as
variáveis ModeloPerc e Perc como variáveis do WorkSpace. Esta prática,
Explicando-o de maneira sucinta, ele se baseia em dois laços. embora não muito recomendada para aplicações e de extrema utilidade
Um mais externo que fica apresentando o conjunto de treinamento ao no teste de nossas aplicações.
perceptron e testando se a saída obtida é igual a desejada. Caso a saída
obtida seja diferente da saída desejada, os pesos serão atualizados. O Tente mudar o conjunto de treinamento e o conjunto de saídas
outro laço fica rodando até que todos os exemplos do conjunto de treino esperadas para que seu perceptron aprenda outras funções lógicas, tais
sejam apresentados e todas as saídas batam. como a função Or ou a função Not.

328 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 329


Construindo uma Aplicação: Simulador de Redes Neurais Criando a interface com o usuário

update: anAspect with: anObject


17.7 Criando a interface com o usuário |gc|
Agora que o modelo da aplicação já está pronto, passemos a gc := self graphicsContext.
criar a interface com o usuário para a apresentação da informação (anAspect == #fimTreino) ifTrue:[
gerada e para a interação do usuário com a nossa aplicação. gc displayString: 'O Treino do Perceptron foi executado com
sucesso!' at: 10@10.].
Perceptron- O primeiro passo a ser tomado é criar um view. A classe View (anAspect == #estatisticas) ifTrue:[
View tem como única função apresentar as informações do modelo da aplica- gc displayString: ('numEpocas= ',(self model numEpocas
ção. Para perfazer a comunicação entre o modelo da aplicação e a inter- printString)) at: 10@30.
face do usuário, o modelo MVC utiliza um conceito do Smalltalk
chamado, mecanismo de dependência, que permite que ao se alterar o gc displayString: (self model conjDeTreinamento
estado interno de um objeto, todos os seus dependentes sejam informa- printString) at: 10@50.
dos. gc displayString: (self model conjSaidas printString) at:
10@70.
Smalltalk defineClass: #PerceptronView ].
superclass: #{UI.View}
indexedType: #objects (anAspect == #teste1) ifTrue:[
private: false gc displayString: (self model perceptron fornecaSaida: #(-
instanceVariableNames: '' 1 -1)) printString at: 10@90.
classInstanceVariableNames: '' ].
imports: '' (anAspect == #teste2) ifTrue:[
category: 'Aplicacoes Perceptron' gc displayString: (self model perceptron fornecaSaida: #(-
1 1)) printString at: 10@90.
Exemplo 17.18 Template para a criação da classe PerceptronView
].
Note que quase todo o código necessário para o funcionamento (anAspect == #teste3) ifTrue:[
gc displayString: (self model perceptron fornecaSaida: #(1
de nossa aplicação já está escrito nas superclasses. Em nossas classes
-1)) printString at: 10@90.
especializadas necessitamos apenas reescrever os métodos que se
].
farão necessários. Aqui por exemplo apenas necessitaremos reescrever (anAspect == #teste4) ifTrue:[
o método mostrado no exemplo 17.19. Ele é responsável pela comunica- gc displayString: (self model perceptron fornecaSaida: #(1
ção entre o model e o view. Utiliza o mecanismo de dependência discu- 1)) printString at: 10@90.
tido anteriormente. ].
Exemplo 17.19 Código do mecanismo de dependência
Relembrando Quando o objeto pai sobre alguma alteração, ele pode informar
dependência seus dependentes através da mensagem changed. Todos os seus dependentes são então informados da alteração do estado do objeto pai,
e podem, através da mensagem update alteram seu próprio estado.

330 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 331


Construindo uma Aplicação: Simulador de Redes Neurais PerceptronController

17.8 PerceptronController
objeto pai A função do controller é prover interação do usuário com a apli-
cação capturando e tratando as entradas do mouse e do teclado e infor-
mando ao view e ao model do esquema MVC que uma entrada ocorreu.
Nesta nossa primeira aplicação apenas utilizaremos o controller para
capturar os cliques do botão direito do mouse e a ele associarmos um
menu para perfazer ações na nossa aplicação.
dependente 1 dependente 2

Figura 17.4 Mecanismo de Dependência


Controller

Figura 17.5 Esquema do controller

A definição da classe é extremamente simples e fica como


segue:

Smalltalk defineClass: #PerceptronController


superclass: #{UI.ControllerWithMenu}

indexedType: #objects
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: 'Aplicacoes Perceptron'

Exemplo 17.20 Template para a criação da classe PerceptronController

332 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 333


Construindo uma Aplicação: Simulador de Redes Neurais PerceptronController

A superclasse que utilizamos é ControllerWithMenu, que é uma Todo o resto do mecanismo de comunicação entre as outras Comunicação
especialização da classe Controller e que adiciona a funcionalidade de duas partes da aplicação, o View e o Model já são herdadas, necessita-
associar um menu ao botão direito do mouse. mos então apenas criar os métodos referentes aos itens de menu.

Definindo Para a definição do menu que utilizaremos, reescrevemos o mostreEstatisticas


menus método initializeMenu definido na classe ControllerWithMenu. Este
método será executado quando a classe for instanciada e o nosso menu, self model changed: #estatisticas with: nil.
automaticamente será criado. “---------------------------------------“
treine
initializeMenu
self model treine.
|menu menuItemGroup subMenu|
“---------------------------------------“
menu := Menu new.
teste1
menu backgroundColor: ColorValue lightCyan.
"teste -1 -1"
menuItemGroup := OrderedCollection new
self model changed: #teste1 with: nil.
add: ((MenuItem labeled: 'Estatisticas') value:
#mostreEstatisticas);
“---------------------------------------“
add: ((MenuItem labeled: 'Treine') value: #treine);
teste2
add: ((MenuItem labeled: 'Inspect model') value:
"teste -1 1"
#inspectModel);
self model changed: #teste2 with: nil.
add: ((MenuItem labeled: 'Inspect view') value:
#inspectView);
“---------------------------------------“
add: ((MenuItem labeled: 'Inspect controller') value:
teste3
#inspectController);
"teste 1 -1"
asArray.
self model changed: #teste3 with: nil.
menu addItemGroup: menuItemGroup.
“---------------------------------------“
menu addLine.
teste4
subMenu := Menu new addItemGroupLabels: #('-1 -1' '-1 1' '1 -1'
"teste 1 1"
'1 1').
self model changed: #teste4 with: nil.
subMenu values: #(#teste1 #teste2 #teste3 #teste4).
subMenu backgroundColor: ColorValue lightCyan. Exemplo 17.22

menu addItem: ((MenuItem labeled: 'Testar') submenu: subMenu).


Uma boa prática durante o tempo de desenvolvimento de uma
self menuHolder: (ValueHolder with: menu) aplicação e incluir entradas para a inspeção do código. Isso não é muito
Exemplo 17.21 Inicialização programática do menu
comum para programadores experimentados em outras linguagens,
como por exemplo C, mais com o tempo você perceberá que esta é uma
das maiores facilidades do Smalltalk, e que é uma prática muito útil que
facilita a depuração do seu programa.

334 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 335


Construindo uma Aplicação: Simulador de Redes Neurais

inspectModel
self model inspect.
“---------------------------------------“
Capítulo 18 &ULDomRGH
inspectView
self view inspect.
“---------------------------------------“
$SOLFDo}HVSDUD
inspectController
self inspect. :::
Exemplo 17.23 Métodos para a inspeção dos objetos model, view, controller

Neste capítulo você vai aprender a construir uma aplicação cli-


ente-servidor Smalltalk que pode ser disponibilizada em rede e acessada
por qualquer browser através do protocolo HTTP. Você vai também apren-
der a configurar o servidor HTTP específico para este fim que acompanha
o conjunto de parcels denominado VisualWave.

18.1 VisualWave e Aplicações na Web


Aplicativos que rodam na web hoje em dia são cada vez mais
Figura 17.6 Janela da aplicação
populares, e como não podia deixar de ser, o VisualWorks fornece uma
maneira de se escrever aplicações para rodar sob o http.
O VIsualWave é um conjunto de parcels que permite que facil-
mente publiquemos na web, aplicações escritas originalmente em Small-
talk. Várias características devem ser observadas com relação ao
VisualWave.
• As aplicações rodam do lado do servidos e são traduzidas em
html para o cliente.

336 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Criação de Aplicações para WWW Executando uma Aplicação

• Qualquer máquina servidora pode, potencialmente, ser um servi- • Web Position


dor de aplicações smalltalk, desde que possua uma máquina vir- • Web
tual para ele.
Elas permitem que, em ordem, definamos código java Script a
• Não é necessário nenhum plug-in adicional para rodar apli-
ser executado em decorrência de algum evento, descrição de copatibili-
cações escritas em Smalltalk. Potencialmente, qualquer internet
dade HTML do componente, e posicionamento do componente na
browser roda.
página. Na aba Web ficam algumas outras propriedades que variam bas-
• A performance das aplicações fica limitada em última instância
tante de componente para componente
pela capacidade de processamento do servidor e da velocidade
da conecção.
Uma vez que o parcel do VisualVave já esteja carregado, basta Criando e
que criemos um servidor de aplicaçõe web para que aplicações possam rodando um
ser executadas através de um browser. servidor
18.2 Instalando e Configurando o VisualWave
Para criarmos um servidor basta que cliquemos no botão Create
Instalar o VisualWave é uma tarefa bem simples. Devemos ape- e um novo servidor será criado. De posse de um novo servidor, podemos
nas carregar um parcel chamado VisualWave 5i.3. utiliza-lo diretamente ou alterar suas configurações. A figura 18.8 mostra
o Web server com um servidor rodando. Este servidor possui as configu-
Após a carga do parcel várias coisas mudarão na interface do
rações padrão definidas pelo VisualWave.
VisualWorks, principalmente no UIPainter. A primeira modificação já
podemos identificar no próprio VisualLaucher. O ícone abaixo será então O campo Port indica a porta de comunicação que será utilizada
adicionado a barra de ícones. Ele nos permite que configuremos o servi- para receber e enviar dados da aplicação. Já o campo Hostname indica o
dor de aplicações web como veremos mais a frente. nome do computador Para testes podemos utilizar o nome "localHost"
indicando que estamos utilizando o computador em que estamos desen-
volvendo. A caixa de checagem permite que o servidor seja executado
toda vez que carregarmos o arquivo imagem e por último, os radio but-
tons permite-nos que definamos a polítuca de tratamento de erros. Para
tempo de desenvolvimento devemos utilizar a segunda opção (Allow
Figura 18.7 Ícone do server console error notifier on Server). Depois que a aplicação estiver finalizada e devi-
damente testada devemos utilizar a segunda opção (trap all errors).
Ao abrirmos o UIPainter também veremos vários outros widgets Note que para que servidor do VisualWave esteja rodando, o
adicionados pelo VisualWave. Eles servem por exemplo para incluir arquivo imagem onde ele foi criado deve estar carregado.
código HTML nos canvas. Veremos nas próximas seções para que ser-
vem cada um dos novos widgets.Também podemos ver alterações no
tocante as propriedades dos widgets antigos. Quatro novas abas de pro-
priedades serão adicionadas:
18.3 Executando uma Aplicação
• JS Events A partir do momento que o servidor VisualWave estiver configu-
• Web Notes rado, podemos executar potencialmente qualquer aplicação existente

338 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 339


Criação de Aplicações para WWW Como Escrever Aplicações Web?

componente descrição
host.domain Indica o nome do servidor e seu domínio
Indica a porta de comunicação que deverá ser utilizada. Deve ser
port
a mesma que a configurada no VisualWave Web Serber.
Prefixo reconhecido pelo TinyHttpServer. De início são reconheci-
dos três prefixos:
• echo - retorna informações das requisições ao servidor
pathPrefix
para o browser. Serve para testar conecções.
• lauch - inicia aplicações
• submit - interação com aplicações em funcionamento.
Indica a aplicação a ser iniciada. Deve ter a mesma grafia que o
path
nome da classe.
Tabela 18.1 componentes do endereço de uma aplicação web no VisualWave

http://localhost:8008/launch/Tools.CodingAssistant
Figura 18.8 Janela do VisualWave Server Console Exemplo 18.1 Abrindo o CodingAssistant em um browser

dentro do nosso arquivo imagem. O endereço para acesso das aplica- Este resultado um tanto quanto pobre de tradução de interfaces
ções, que deve ser digitado em um browser de páginas possui a seguinte pelo VisualWave ocorre unica e exclusivamente porque o CodingAssis-
sintaxe: tant não foi projetado para ser executado na web.
http://host.domain:port/pathPrefix/path
A tabela 18.1 detalha cada uma das partes do endereço
18.4 Como Escrever Aplicações Web?
O exemplo 18.1 mostra como podemos abrir o CodingAssintant
em um browser. Note na figura 18.9 a diferença de formatação existente O mais interessante do VisualWave é que ele permite que escre-
entre a aplicação aberta no Smalltalk e no Internet Explorer. vamos nossas aplicações web exatamente igual ao processo de escre-
ver aplicações desktop.
Note que muito da formatação do CodingEditor foi perdida ao
abrirmos o mesmo no browser. Ocorre também que o botão que estava Porém como o VisualWave traduz os widgets para HTML, exis-
desabilitado não foi apresentado. Isso ocorre porque para o VisualWave, tem alguns widgets que não são traduzidos corretamente. Por exemplo,
quando um componente está desabilitado ele é interpretado como com- um grid é traduzido como uma tabela com radio buttons em cada célula.
ponente invisível. Desta forma, a melhor maneira de se escrever uma aplicação
para web em Smalltalk é ir testando passo-a-passo a aprarência e o fun-
cionamento de sua aplicação.

340 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 341


Criação de Aplicações para WWW Como Escrever Aplicações Web?

• Aplicações web devem ser thread-save, isso porque potencial-


mente, multiplos usuários estarão acessando a aplicação ao
mesmo tempo.
• No visualWorks, cada widget é manipulado individualmente.
Como aplicações web devem rotar em multiplas instancias,
vários widgets serão alterados e submetidos ao mesmo tempo.
nestes casos, o VisualWorks processa cada um por vez
seguindo a sequência de tab.
• A especificação atual do HTML imposibilita que formatação de
interface de maneira adequada e o esquema de posicionamento
relativo pode não funcionar. Uma boa prática para minimizar os
problemas de tradução da interface para HTML é agrupar os
widgets.

Como alguns dos widgets padão do smalltalk não possuem um Widgets não
euqivalente em HTML, eles simplesmente não são suportados. Quando suportados
posicionamos um destes widgets não suportados em um canvas eles
ficarão invisíveis. Para saber mais sobre como o VisualWave suporta os
widgets posicione qualquer widget em um canvas e então verifique suas
propriedades. Com o VsualWave instalado, novas abas de propriedades
serão adicionadas. Veja a chamada Web notes. A seguir vemos uma lista
dos widgets que não são suportados:
• ComboBox
• GroupBox
• DataSet
• Region
Figura 18.9 CodingAssintant aberto no Smalltalk e o internet explorer.
• Slider
Existem algumas outras dicas que devem ser observadas ao se • Notebook
escrever uma aplicação web: • SubCanvas
• Como o processamento da aplicação fica do lado do servidor, Existem alguns problemas também em relação a propriedades
devemos evitar automações de interface, tipo formatar iterativa- de widgets que não são suportadas. O leitor pode encontrar toda a infor-
mente um input field, isso porque no VisualWave se espera que mação sobre compatibilidade de widgets e HTML na aba web notes
vários widgets sejam preenchidos e só então os processa. O citada anteriormente.
processamento é feito na ordem dos tabs.

342 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 343


Criação de Aplicações para WWW

18.5 Widgets Específicos do VisualWave


Ao instalarmos o VisualWave alguns novos widgets serão adicio-
Capítulo 19 %LEOLRJUDILD
nados a paletta de widgets. A seguir veremos uma pequena esplicação
de que funcionalidades eles agregam a aplicações web.

Nome Ícone Descrição


Permite que adicionemos recursos de VRML (Virtual
Reality Model Language) a nossas aplicações web. O
VRMLSpec
VisualWave adiciona a biblioteca de classes um fra-
mework de VRML. Vale a pena dar uma olhada.
Permite a utilização de Componentes ActiveX.
ActiveX Cntrl

Adiciona a funcionalidade de criarmos textos formata-


HTML Text dos, as aplicações
EXTREMAMENTE INCOMPLETO = FALTA
Permite que rodemos applets java. Só funciona em
Java Applet tempo de execução em um browser. 1. Instalação do VisualWorks
Tabela 18.2 Novos widgets do VisualWave CINCOM VisualWorks Installation Guide, Utha, 2001.
2. Coleta de lixo e desalocação de memória
CINCOM Smalltalk Application Developer’s Guide, Utha,2001. p.
411-418.
3. Parcels
CINCOM Smalltalk Application Developer’s Guide, Utha,2001. p.
125-142.
4. Manipulação dos arquivos de alteração
CINCOM Smalltalk Application Developer’s Guide, Utha,2001.
p.146 - 154.
5. ImageMaker:
CINCOM Smalltalk Application Developer’s Guide, Utha,2001. p.
237-251.

344 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Bibliografia

/LVWDGH)LJXUDV
6. SPICE:
YASUMATSU, Kazuki. A Translation Method from Smalltalk into
Interoperable C Code. 1996, 101f. Dissertação (Doutorado em Engenha-
ria) - Graduate School of Engineering Science of Osaka University, Osaka.

Conceitos Básicos do Ambiente


Janela de Instalação do VisualWorks 5i.3 38
Janela de associação de arquivos do windows 40
Janela de localização de arquivos do windows 41
Janela de salvamento da imagem 42
Janela de saída do VisualWorks 42
Laucher do VisualWorks 44
Botões para abertura dos browsers 45
O System Browser do VisualWorks 46
Menu PopUp do View de Categoria e janela para localização de classes 48
Jjanela de multiplas ocorrências de uma pesquisa 48
Janela para criação de categorias 49
Janela para criação de protocolos 50
Template para a criação de classes. A nova classe criada será neste caso incluída
na categoria “Colections-Arrayed” selecionada. 51
Exemplo do Hierarchy Browser para uma classe denominada “Retangulo”. 54
Workspace do VisualWorks 55
Código selecionado no workspace 56
Popup menu aberto a partir do botão direito do mouse 57
Resultado do execução da opção print it 58

346 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Janela do Resource Finder 59 Implementação da mensagem changed 182
UIPainter com suas 3 janelas mais comuns abertas 60
Janela de propriedades de um botão 62
Janela de configuração do VisualWorks 63
Processos e Semáforos
Botões para abertura dos browsers de Parcels 66 Implementação da mensagem fork na classe BlockClosure 190
Janela para carga de novos parcels 67 Esquema das principais prioridades pré-definidas 193
Janela para remoção de parcels 68
Browser para criação e gerenciamento de parcels 69
Classe Teste recém criada, com as variáveis de instância a, b e c. 74 Captura e Tratamento de Exceções
Hierarquia de classes reduzida das exceções 208
Busca recursiva do erro 209
Conceitos Básicos da Linguagem
Janela de tratamento de exceções padrão do VisualWorks 213
System Browser e opções classe, instância e variáveis compartilhadas 80 execução do exemplo 11.2 215
Mecanismo de execução de uma mensagem 83
Definição do método “**” na classe Number 90
Janela de inspeção contendo os dados relativos a um número 91 Superfícies gráficas, contexto gráfico e primitivas gráficas
Implementação da mensagem ‘@’ da classe Point 99 Exemplo de uma mesma janela no Windows e no Linux sob KDE 228
Resultado do código do exemplo anterior 232
Desenho de linhas cruzadas gerado pelo código do exemplo anterior 235
Mensagens e Métodos
Resultado da execução do código de geração de retângulos 239
Implementação da mensagem binária + 105 Curva spline gerada pelo código do exemplo anterior 241
Exceção criada pelo envio de uma mensagem inválida 116 Hierarquia das classes de imagem em Smalltalk 246
Indentação padrão utilizada na biblioteca de classes 122 execução do exemplo 12.17 251
Exemplo de método nao decompilado 123
Exemplo de método decompilado 123
Eexemplo de utilização da mensagem ‘copy’ 125 Criando GUIs Interativamente
Exemplo de um método de classe 128 Janela-exemplo 260
icone de recursos de interface 262
Método de classe definindo uma interface gráfica para todas as instâncias 263
Variáveis
Propriedades de um botão 264
Esquema de classes de armazenamento de variáveis no VisualWorks 132 Interface-exemplo 266
Declaração da classe OrderedCollection 138 Aba de proporções e posição de um widget 267
Janela para a definição do tipo de variáveis 143 Filosofia de definição de tamanho através dos cantos de objetos 267
Ferramentas de alinhamento e espaçamento 268
Janela do exemplo de value holders 270
Mecanismo de Dependênica Esquema de janelas em 3 sistemas distintos 272
funcionamento básico do mecanismo de dependência 178
Dependência de um ou vários pais 179

348 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 349


Janelas de diálogo Criação de Aplicações para WWW
Janela de aviso simples 278 Ícone do server console 338
Janelas de diálogo: Uma janela de pesquisa inválida, janela para escolha do tipo de Janela do VisualWave Server Console 340
variáveis e uma janela de saida do ambiente. 280 CodingAssintant aberto no Smalltalk e o internet explorer. 342
Janela de requisição de um novo Alfa 281
Janela para pesquisa de classes 281
Janela de múltipla seleção 282

Menus
O Menu Editor sobre um menu vazio 285
Botões para a criação de itens de menu 286
Botões para reposicionamento dos itens de menu 286
Janela para instalação de um menu como recurso 287
Ícone que representa um menu como recurso 287
Aba de propriedades do Menu Editor 288
Aba de propriedades Details do Menu Editor 290
Menu gerado pelo código do exemplo 15.2 292
Menu criado utilizando a classe MenuBuilder 293
Menu produzido pelo código do exemplo 15.4 295
Definindo uma barra de menu 296
Exemplo de utilização de menu 298

O paradigma MVC (Model-View-Controller)


Arquitetura MVC 303
Hierarquia de classes de Model 305
Hierarquia de classes de Controller 309

Construindo uma Aplicação: Simulador de Redes Neurais


Modelo computacional do neurônio de Hebb 314
Função de ativação em degrau ou limiar 315
Hirarquia de classes com uma classe NeurônioArtificial como classe abstrata. 317
Mecanismo de Dependência 332
Esquema do controller 333
Janela da aplicação 336

350 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 351


/LVWDGH7DEHODV

Conceitos Básicos do Ambiente


Convenções adotadas pelo parcel browser 70

Conceitos Básicos da Linguagem


Convenções de nomeação em Smalltalk 87
Correlação entre várias bases numéricas 94
Exemplos de simbolos válidos 97
Exemplos de simbolos inválidos 97

Mensagens e Métodos
Regras para formação de mensagens 104
Mensagens binárias mais comuns 106
Regras de precedência de menságens 114
Protocolos comumente utilizados pela biblioteca de classes 126

Blocos, estruturas de controle e seleção


Tipos de laços condicionais 151

352 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


/LVWDGH([HPSORV
Mecanismo de Dependênica
Protocolos dos métodos referentes ao mecanismo de dependência 181

Processos e Semáforos
Métodos para a criação de instancias da classe Delay 195

Captura e Tratamento de Exceções


Subclasse de Exception 214
Métodos comumente utilizados 218
Ações pós-ocorrência de uma exceção 219

Superfícies gráficas, contexto gráfico e primitivas gráficas


Estilos de texto 230
Métodos que mudam o estilo de uma instância de Text 233 Conceitos Básicos do Ambiente
Métodos implementados por LineSegment 233
Métodos implementados por Polyline 238 Reabertura do visual laucher 44
Métodos implementados pela classe Rectangle 240
Algumas outros métodos da classe Rectangle 243 Mensagens e Métodos
Cursores padrão 256
Envio da mensagem “rounded” ao número ponto flutuante 123,4 102
Exemplo de mensagens unárias 103
Criando GUIs Interativamente Símbolos comumente utilizados para compor mensagens binárias 105
Funcionalidades de Programação Visual de Interfaces em VisualWorks 273 Mensagens binárias 106
Ordem de execução das mensagens 107
Mensagens por palavra chave 110
Menus Duas mensagens encadeadas 111
Algumas mensagens para acesso e alteração de ítens de menu 292 Exemplo sem a utilização do encadeamento de mensagens 111
Métodos para a criação de menus da classe MenuBuilder 295 Exemplo utiilzando o encadeamento de mensagens 112
Cascateamento de mensagens utilizando “ ; “ 112
Exemplo de cascateamento de menságens em uma única linha 113
Criação de Aplicações para WWW Utilização da menságem ‘yourself’ 114
Mensagem enviada para um objeto que não a implementa 115
componentes do endereço de uma aplicação web no VisualWave 341
Exemplos de nomes para métodos 117
Novos widgets do VisualWave 344
Outros exemplos de nomes para métodos 117

354 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo


Exemplos de métodos para conversão e que retornam booleanos 118 Código para uma query SQL usando streams 164
Métodos de acesso a atributos 119 Duas formas de criar um manipulador para um arquivo a partir de seu nome 167
Método que altera o estado interno do objeto 120 Duas formas de concatenar o caminho e o nome de um arquivo 168
Construindo o nome e caminho de arquivo a partir de seus elementos 168
Manipulando o nome de um arquivo 169
Variáveis Criando, escrevendo e fechando um arquivo texto 172
Declaração de variáveis em C 133 Escrevendo texto em um arquivo em modo binário 172
Definição de variáveis nomeadas 136 Código para ler um bitmap de tonalidades de cinza em formato PGM 174
Criação dos métodos de acesso 136
Tipos das variáveis indexadas 137
Variável temporária dentro de um método 138
Processos e Semáforos
Variáveis temporárias em blocos 140 criação de um processo através da mensagem fork 190
Outro exemplo de variáveis em blocos 140 exemplo de criação de processos através do envio da mensagem newProcces 191
Mais um exemplo de variáveis em blocos 140 Exemplo de uso da mensagem terminate 191
Utilização de variáveis tipo class instance 141 uttilizando instancias de Delay com processos 195
utilização da mensagem supend 196
Exemplo de utilização da mensagem yield 196
Blocos, estruturas de controle e seleção
utilização da mensagem interruptWith: 197
Retorna o resultado da operação matemática. 149 comunicação entre processos atraves de filas compartilhadas 199
Retorna o resultado da comparação. 149 Uma mensagem é enviada a um semáforo 200
Forma mais simples de uma estrutura de repetição usando mensagens 150 Ordem de execução 201
Iteração com passo definido pelo programador 151
Laço com limites definidos pelo programador 151
Trechos de código para os diferentes tipos de laço condicional 152 Captura e Tratamento de Exceções
Utilização de mensagens de seleção condicional 153 Tratamento do erro divisão por zero 211
Código para impressão de todos os elementos de uma lista 154 Outra forma de capiturar exceções 215
Código para encontrar um elemento igual a 2 numa lista 155 outras formas de tratar a mesma exceção 216
Código que retorna o número de caracteres-espaço em uma string 155 Sinalizando uma exceção explicitamente 217
Código que retorna o número de caracteres não brancos em uma string 155 Equivalente ao exemplo 11.4 218
Código que retorna uma nova string contendo a string receptora em maiúsculas 155 Gerenciamento de multiplos erros 219
maneiras alternativas de se cirar uma instancia padrão de Error 220
Manipulação de arquivos e estruturas de acesso seqüencial
Criação de uma stream habilitada para escrita 160 Superfícies gráficas, contexto gráfico e primitivas gráficas
Criação de uma stream somente para leitura 160 capturando o contexto gráfico 226
Criação de uma stream para leitura e escrita e inclusão de um novo elemento 161 criando uma janela em branco 229
Usando um array como novo stream de leitura-escrita apagamos seu conteúdo 161 Desenhando texto formatado em um contexto gráfico 231
Incluindo dados em um stream préexistente 162

358 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 359


Mostrando linhas cruzadas 234 O paradigma MVC (Model-View-Controller)
Mostrando polígonos 236
Desenha uma curva cúbica paramétrica (Hermite) 237 Maneiras de se crar um ValueHolder 306
Criando e mostrando retângulos 238
Desenhando uma curva paramétrica de Béier 240 Construindo uma Aplicação: Simulador de Redes Neurais
Desenhando uma curva paramétrica spline 241
Escalonamento de um retângulo 242 Declaração da classe NeuronioArtificial 317
movimentando retângulos do contexto gráfico 243 Método de classe para criação de instâncias 318
utilizando wrappers de atributos gráficos 245 Métodos agrupados sob o protocolo accessing 319
Capturando uma imagem da tela 247 Métodos abstratos 320
Criando uma imagem em branco 247 métodos para inicialização dos atributos da classes 321
criando uma imagem bit a bit 248 template para a criação da classe Perceptron 321
Imagem com 3 bytes por linha 250 Método para criação de instancias 321
Abrindo uma imagem de um arquivo 250 métodos de acesso ao estado do objeto 322
Obtendo um pixmap através de uma imagem 252 métodos para inicialização do estado interno do objeto 322
icone a partir de uma imagem com paletta de transparências 253 função de ativação degrau 323
Criando um cursor programacionalmente 255 Template para a criação da classe ModeloPerceptron 325
Método de classe para a criação de instancias 325
Método que inicializa o estado interno do objeto 326
Criando GUIs Interativamente método para a criação e abertura de uma janela 326
Métodos de acesso do perceptron 327
Definição de uma interface em sintaxe Smalltalk 261
Algorítmo de aprendizado do perceptron 328
código do exemplo de value holders 271
Código para teste da aplicação 329
Template para a criação da classe PerceptronView 330
Janelas de diálogo Código do mecanismo de dependência 331
Template para a criação da classe PerceptronController 333
Método mostrando uma mensagem de erro que abre uma caixa de aviso 279
Inicialização programática do menu 334
Código para a janela anterior 281
Métodos para a inspeção dos objetos model, view, controller 336

Menus
Criação de Aplicações para WWW
Código para gerar dinamicamente um menu simples 290
Abrindo o CodingAssistant em um browser 341
Código para gerar dinamicamente um menu com valores de retorno 292
Construindo um menu utilizando recursos da classe MenuBuilder 294
Construindo um menu usando código para menus padronizados 295
Menu-exemplo 295
Modificação do código 297

360 D.D.Abdalla e A.v.Wangenheim Smalltalk Completo 361

View publication stats

Você também pode gostar