Onde as variáveis ​​de classe são definidas em Smalltalk?

Jan 19 2021

Eu queria saber, se eu definir uma nova variável de classe, por exemplo, para a classe MyClass, a definição vai estar em MyClassou em MyClass class? Ao MyClass classmenos sabe sobre a nova variável de classe?

Respostas

5 LeandroCaniglia Jan 20 2021 at 00:36

Sim, as variáveis ​​de classe são compartilhadas com a classe e a metaclasse. Eles também são compartilhados com todas as subclasses (e suas metaclasses). Uma variável de classe geralmente é capitalizada, para transmitir melhor a ideia de ser compartilhada em um escopo mais amplo do que a classe. Você define variáveis ​​de classe na classe (não na metaclasse).

Variáveis ​​de classe não devem ser confundidas com variáveis ​​de instância de classe, que são variáveis ​​de instância definidas no nível da metaclasse, isto é, variáveis ​​de instância do objeto de classe. Essa noção é um tanto obscura, apesar de sua simplicidade (ou por causa dela): variáveis ​​de instância são sempre definidas na classe para definir a forma (slots) de suas instâncias . Assim, se aplicarmos essa definição à metaclasse, que é a classe da classe, uma variável de instância definida aqui define a forma de suas instâncias, das quais há (normalmente) apenas uma, a classe.

Voltando às variáveis ​​de classe, você as define na classe (lado inst) e as inicializa na metaclasse (ou seja, lado da classe). Lembre-se de que esses são globais (parciais) no sentido de que serão compartilhados entre instâncias, sub-instâncias, subclasses e metaclasses e, portanto, devem ser tratados com o cuidado usual com que tratamos os globais.


Mais um esclarecimento

Quando dizemos que variáveis ​​de instância são compartilhadas entre instâncias e subinstâncias, queremos dizer seus nomes (e posições na memória dos slots de objetos); não queremos dizer seus valores (conteúdo dos referidos slots). Assim, duas instâncias da classe Ccompartilharão o nome, digamos color, se a classe definir o ivar color, mas seus valores em cada uma das instâncias serão independentes. Em outras palavras, o que é compartilhado é o nome, não o valor.

Com as variáveis ​​de classe, o que é compartilhado é o nome e o valor. Na verdade, é o Associationobjeto, por exemplo Theme -> aTheme, o que é compartilhado. Consequentemente, qualquer modificação no valor de uma variável de classe afeta todas as suas referências. Este não é o caso com variáveis ​​de instância de classe porque elas nada mais são do que variáveis ​​de instância, exceto que moldam a classe e suas subclasses, em vez de instâncias regulares e subinstâncias.


Para obter mais informações sobre as variáveis ​​Smalltalk, consulte https://stackoverflow.com/a/42460583/4081336

2 aka.nice Jan 20 2021 at 23:59

Apenas como um complemento à resposta de Leandro, aqui está o principal método específico de implementação do Squeak que explica o compartilhamento de variáveis ​​de classe entre o lado da instância (classe) e o lado da classe (metaclasse):

Metaclass>>classPool
    "Answer the dictionary of class variables."

    ^thisClass classPool

onde thisClassestá a instância única da Metaclass, que é a própria classe ...

Existem grandes chances de encontrar implementações semelhantes na maioria dos dialetos Smalltalk.

O compilador tentará primeiro resolver a variável como um método / bloco temporário (incluindo parâmetros methd / bloco), depois as variáveis ​​de instância e depois as variáveis ​​compartilhadas.

O método classPool é enviado pelo compilador nesta última fase.

Leandro explicou que o compilador resolve a ligação apenas como um deslocamento que será transcrito diretamente no bytecode no caso de slot de variável de instância ou variável temporária de método, ou como um tipo de associação para o caso de variável compartilhada, sendo esta associação geralmente adicionado aos literais CompiledMethod e efetivamente compartilhado entre todos os métodos que lidam com esta variável (todos os métodos apontam para o mesmo objeto Assocation que é efetivamente compartilhado).

A parte do compilador é muito mais específica do dialeto, no Squeak, é este método que é usado para resolver a ligação de variáveis ​​compartilhadas:

class>>bindingOf: varName environment: anEnvironment
    "Answer the binding of some variable resolved in the scope of the receiver"
    | aSymbol binding |
    aSymbol := varName asSymbol.

    "First look in local classVar dictionary."
    binding := self classPool bindingOf: aSymbol.
    binding ifNotNil:[^binding].

    "Next look in local shared pools."
    self sharedPools do:[:pool | 
        binding := pool bindingOf: aSymbol.
        binding ifNotNil:[^binding].
    ].

    "Next look into superclass pools"
    superclass ifNotNil: [^ superclass bindingOf: aSymbol environment: anEnvironment].

    "No more superclass... Last look in declared environment."
    ^anEnvironment bindingOf: aSymbol

Isso é para lembrá-lo de que uma das partes mais interessantes do Smalltalk é que você pode se aprofundar na implementação de dentro do IDE. Smalltalk é essencialmente escrito em Smalltalk!