O modelo de objeto Gambas

1. Objetos & Classes

Um objeto em Gambas é uma estrutura de dados que fornece propriedades, variáveis, métodos e eventos.

Os objetos são acessados "por referência", ou seja, usando um ponteiro para ele, ou usando uma variável cujo valor é o endereço da estrutura de dados do objeto na memória.

Você pode ver o endereço de um objeto usando a instrução PRINT:

Dim aStr As New String[]

Print aStr

(String[] 0x80dccf8)

A estrutura de dados do objeto é descrita por uma classe.

1.1. Classes

Cada objeto Gambas tem uma classe que descreve todas as propriedades públicas, métodos e eventos. Essa classe também é um objeto Gambas, cuja classe é a classe com o nome Class.

A classe estática é uma classe cujos membros são todos static (veja abaixo). Em Gambas, uma classe estática também é chamado de module.

A classe estática não pode ser instanciado: seria criar um objeto com nenhuma variável dinâmica, o que é inútil.

Exemplo

A classe System é uma classe estática: todos os seus métodos são estáticos, e você não pode criar um objeto cuja classe seria System.

A classe virtual é uma pseudo-classe oculta que você não pode manipular explicitamente.

1.2. Propriedades, métodos e variáveis

Propriedades e métodos permitem manipular a estrutura de dados.

Uma Propriedades, um Métodos ou uma Variável pode ser static:
  • A variável estática será compartilhada por todas as instâncias da mesma classe.

  • A propriedade estática ou método só podem modificar variáveis estáticas.

Um método ou uma variável pode ser tanto public como private. A propriedade é sempre pública.

Símbolos privados só podem ser usado dentro da classe. Símbolos públicos podem ser usado em todos os lugares, desde que você tenha uma referência para o objeto.

1.3. Referências

Não há coletor de lixo em Gambas. Assim, cada objeto tem um contador de referência que é incrementado cada vez que o objeto é referenciado por qualquer variável, array, collection ou outro objeto, e decrementado quando ele é liberado.

Este contador de referência é zero na criação do objeto, e ele se torna zero novamente após um lançamento de referência, quando o objeto é liberado.

1.4. Objetos inválidos

Um objeto pode se tornar inválido. Porque, por exemplo, está ligado a um objeto interna não gerenciado pelo Gambas que foi destruído.

A tentativa de usar um objeto inválido gera um erro.

1.5. Métodos especiais

Métodos especiais são métodos declarados nas classes, cujo nome começa com um caractere sublinhado, e que são chamados pelo interpretador nas seguintes situações:
  • Quando um objeto é criado.

  • Quando um objeto é liberado.

  • Quando a classe do objeto é carregada.

  • Quando a classe de objeto é descarregada.

  • Ao usar um objeto como se fosse uma matriz.

  • Ao enumerar o objeto.

  • Ao usar um objeto como se fosse uma função.

  • Quando um objeto é conectado ou separado de seu pai.

  • Ao tentar utilizar um objeto desconhecido, método ou propriedade.

Veja Métodos Especiais e Special Methods para mais informações.

2. Eventos e observadores

2.1. Eventos

Os eventos são sinais enviados por um objeto quando acontece alguma coisa sobre ele.

Se um objeto gera eventos, que irá realizar uma referência em seu observador padrão, ou objeto pai.

Este observador padrão é outro objeto que implementa manipuladores de eventos. O event handler é apenas um método público que é chamado cada vez que o evento é gerado.

Por padrão, o observador é o objeto atual, onde o objeto recém-instanciado é declarado.

Para levantar eventos, um objeto deve ter um nome de evento. O nome do evento é atribuído a instanciação do objeto, ao usar a instrução NEW e a palavra-chave AS, é o prefixo de todos os métodos do manipulador de eventos.

Exemplo

Isso cria um controle Button que irá gerar eventos.

Dim hButton As Button

hButton = New Button(Me) As "ButtonEventName"

Public Sub ButtonEventName_Click()

Print "Este é o manipulador de evento 'Click' para o botão anterior."

End

Se nenhum nome do evento é especificado, então o objeto não irá gerar eventos.

2.2. Objeto pai Padrão (ou padrão default observer)

Alguns objetos podem ter um objeto pai padrão se você não defini-lo, especificando um nome de evento com a sintaxe As "xxx".

No momento, os únicos objetos que tem um objeto pai padrão são os forms, que utiliza a si mesmo como objeto pai padrão. Isto foi feito para imitar o comportamento do Visual Basic™ e ajudar os desenvolvedores do velho VB.

Se você criar um formulário e especificar o seu nome de eventos com a sintaxe As "xxx", o comportamento padrão será substituído.

2.3. Bloqueio de Objetos

Um objeto pode ser bloqueado para que ele pare de gerar eventos, e pode ser desbloqueado para que ele levante-os novamente. Veja os métodos Object.Lock and Object.Unlock.

Alguns eventos podem ser cancelados pelo manipulador de eventos, usando a instrução STOP EVENT. O efeito desta anulação depende do evento.

Um objeto é automaticamente bloqueado durante a execução de seu construtor: ele não pode enviar ou receber quaisquer eventos

2.4. Observadores

Observers são objetos que permitem interceptar eventos gerados por outros objetos. Que os observa.

Você pode interceptar eventos antes que eles sejam levantados, ou logo após.

Para cada evento interceptado, o observador vai levantar um evento com o mesmo nome e os mesmos argumentos. Estes eventos são gerados, além do evento original tratado pelo objeto pai.

Se você usar STOP EVENT dentro de um manipulador de evento observador, o evento original é cancelado.

Exemplo

Private $hButton As Button
Private $hObserver As Observer

Public Sub Form_Load()

  $hButton = New Button(Me) As "Button"
  $hObserver = New Observer(hButton) As "Observer"

End

Public Sub Observer_Click()

  Debug "O botão foi clicado. I cancelou o evento!"
  Stop Event

End

Public Sub Button_Click()

  Debug "Se você me ver, esse é um problema!"

End

3. Herança

A herança é o caminho para uma classe se tornar uma versão especializada de outra classe.

3.1. O que é herdado?

A classe herda de seu pai, cada método, propriedade, constante e evento.

Você deve usar a palavra-chave ME para acessar os elementos herdados do código implementado na classe.

3.2. Qual classe pode ser uma classe pai?

Você pode herdar qualquer classe, até mesmo uma nativa!

Por exemplo, você pode criar uma classe MyListBox personalizada que herda ListBox mas, permite associar uma tag com cada item da lista.

Observe que você não pode usar INHERITS em um arquivo de classe de um formulário, porque os formulários já herdam a classe Form .

A profundidade da árvore de herança não pode ser maior do que 16. Esta é uma constante codificada dentro do interpretador Gambas.

3.3. Expedição Virtual

Ao chamar um método ou acessar uma propriedade de um objeto de referência, Gambas sempre usa virtual dispatching.

Isso significa que a classe real do objeto é sempre utilizada, e não o tipo da variável que faz referência ao objeto - como era no Gambas 1.0.

3.4. Herança e construtor

Ao contrário de todas as linguagem objeto, eu sei, cada classe na herança hierarquia consome os parâmetros passados para o construtor.

Vamos supor que temos a seguinte árvore de herança:

MyListBox ---inherits--> ListBox ---inherits---> Control

  • Control._new() não existe.

  • ListBox._new() recebe um parâmetro: o controle pai.

  • MyListBox._new() recebe um parâmetro: um nome - é apenas um exemplo.

Portanto NEW MyListBox terá dois parâmetros.

  • A primeira será enviado para ListBox._new().

  • O segundo a MyListBox._new().

Tenha cuidado: o ListBox._new() será chamado em primeiro lugar, de modo que você tem certeza que o controle ListBox existe quando você está no MyListBox._new().

Então você vai cria um controle MyListBox desta forma:

hMyListBox = NEW MyListBox(hContainer, "Nome")

Assim, a ordem dos argumentos é o seguinte:

  • Os argumentos obrigatórios são executados em primeiro lugar, e, em seguida, os argumentos opcionais, se estiverem disponíveis.

  • Os argumentos das classes mais velhas são especificados em primeiro lugar.

Em Gambas 2.0, a ordem ou argumentos foram invertidos!

Por exemplo, se você tem a seguinte herança:

MyForm --> Form --> Window

com o construtor MyForm sendo:

Sub _new(FirstArg As String, SecondArg as Integer, Optional ThirdArg As Integer)

Nota: o construtor Form não tem nenhum argumento, e o construtor Window tem um argumento pai opcional.

A assinatura do construtor final será:

New MyForm(FirstArg As String, SecondArg As Integer, Optional Parent As Control, Optional ThirdArg As Integer)

De uma maneira mais geral, a ordem dos argumentos para uma árvore de herança de nível três é:

  • Os argumentos obrigatórios do construtor grande-pai.

  • Os argumentos obrigatórios do construtor pai.

  • Os argumentos obrigatórios do construtor final.

  • Os argumentos opcionais do construtor grande-pai.

  • Os argumentos opcionais do construtor pai.

  • Os argumentos opcionais do construtor final.

3.5. Símbolo Substituido

Quando um símbolo for substituído, a assinatura do símbolo na classe filha deve ser o mesmo que a assinatura do símbolo na classe principal.

As regras são:
  • Um símbolo dinâmica deve ser substituída por um símbolo dinâmico, um estático por um estático.

  • Um método deve ser substituído por um método com exatamente a mesma assinatura (mesmos argumentos, tipos de dados, tipo de dados de retorno, se houver).

  • Uma propriedade de read/write deve ser substituída por uma propriedade read/write com o mesmo tipo de dados.

  • Uma propriedade de read-only deve ser substituída por uma propriedade read-only com o mesmo tipo de dados.

  • Uma constante pode ser substituído por uma constante com o mesmo tipo de dados.

4. Componentes

Componente Gambas são bibliotecas externas compartilhadas, escritas em C, C ++ ou em Gambas, adicionam novas funções e / ou classes para o interpretador Gambas.

Classes são agrupados de acordo com o componente de origem.

4.1. Componentes interno padrão

O interpretador inclui um componente interno chamado Classes nativas que define todas as classes padrão da linguagem.

Este componente é sempre carregado por padrão, e pode ser considerado como parte da linguagem.

4.2. Tabelas de símbolos

Cada componente tem sua própria tabela de símbolo de classe privada, de modo que os nomes de classe não entrem em conflito.

4.3. Tabela de símbolos Global

Portanto os componentes podem trabalhar juntos, há uma tabela de símbolos global, onde todas as classes exportadas por componentes e todas as classes exportados pelo projeto atual são armazenadas.

Se houver um conflito de nomes nesta tabela de símbolo global, a última classe carregada substitui a classe anteriormente carregada com o mesmo nome, usando herança. Em outras palavras, a classe predominante a subscreve.

Esta última característica pode ser utilizada para:
  • Estender uma classe já declarada pela adição de novos métodos ou propriedades a ela. Por exemplo, o a classe gb.qt4 Application reimplementa a classe gb Application.

  • Substituindo os métodos de uma classe já declarados. Por exemplo, o componente gb.form.dialog substitui a maioria dos métodos estáticos da classe Dialog.

4.4. Tabela de símbolos do projeto

Seu projeto tem seu próprio símbolo privado, como qualquer componente, e pode exportar qualquer de suas classes para a tabela de símbolo global usando a palavra-chave EXPORT.

As classes do projeto são carregadas depois de todos os componentes. Portanto, sua classe exportado pode substituir quaisquer classes exportadas declaradas em qualquer componente.

Veja também