Metaclasses
(Esta seção não é essencial para um primeiro contato com Smalltalk, mas é inserida neste ponto por coerência com o assunto deste capítulo, e pode ser deixada para leitura posterior).
Como foi descrito nas seções anteriores, toda classe em Smalltalk é também um objeto como qualquer outro e responde a mensagens que fazem parte de seu protocolo particular. Em geral essas mensagens de classe objetivam a criação de instâncias de si mesmas com uma inicialização específica, como a mensagem today para a classe Date, que cria uma nova instância com o valor da data de hoje.
Existe uma classe especial, chamada Behavior (literalmente, comportamento), onde fica localizado o protocolo comum a todas as classes do sistema. Todas as classes, enquanto objetos, são instâncias de Behavior , ou de alguma sub-classe dela. É importante compreender bem essa natureza dual das classes em Smalltalk: de um lado são classes, mas também são instâncias de outra classe. Em outras linguagens, como C++ e Eiffel, classes não são objetos, e não podem portanto receber mensagens.
A mensagem padrão para criar uma nova instância de qualquer classe é new, enviada à própria classe. Como essa mensagem é comum a todas, ela fica localizada na classe Behavior.
Por outro lado, mensagens específicas para cada classe, como today para a classe Date, não podem ficar em Behavior, pois não devem ser compreendidas pelas demais classes. Devem estar em alguma sub-classe de Behavior da qual Date seja uma instância. Essa sub-classe de Behavior é chamada a metaclasse de Date. A classe Date é a única instância de sua metaclasse.
A metaclasse de toda classe C é criada automaticamente, quando C é criada, e C é implementada como a única instância de sua metaclasse. Todas as mensagens específicas para a classe C ficam localizadas na metaclasse de C.
Metaclasses não recebem nomes particulares. Uma referência à metaclasse de uma classe C qualquer pode ser obtida enviando-se a C a mensagem class. A metaclasse de C é portanto referenciada como C class.
Para manter a coerência geral do modêlo, cada metaclasse é também um objeto. Mas, ao contrário das classes, uma metaclasse não é uma instância de alguma outra metaclasse (pois, se assim fosse, haveria uma cadeia infinita de metaclasses de metaclasses de metaclasses, etc!) Cada metaclasse é uma instância de uma classe especial chamada MetaClass.
Além de MetaClass, Behavior possui a sub-classe Class, que
é a super-classe de todas as classes que não são
meta-classes. A hierarquia de classes fica portanto: (parte)
Note que a classe Class também tem sua metaclasse, Class class, da qual Class é instância. Portanto, quando se deseja, em Smalltalk, criar uma mensagem específica para inicializar instâncias de uma classe C qualquer, essa mensagem é incorporada, juntamente com o método correspondente, no protocolo de C class, a metaclasse de C.
Cada classe é automaticamente uma instância de sua metaclasse, como foi visto acima. Note que as metaclasses formam também uma hierarquia a partir da classe Object class, subclasse imediata de Class. Se uma classe A é super-classe de outra classe AA), então A class é também super-classe de AA class. Isto significa que podemos criar mensagens de inicialização que valem para toda uma sub-hierarquia de classes bastando incorporar essas mensagens na metaclasse da classe mais elevada dessa hierarquia. Por exemplo, uma mensagem incorporada ao protocolo da metaclasse de Collection pode ser enviada a qualquer sub-classe de Collection para inicializar instâncias.