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