Saltar para o conteúdo principal
Versão: 20 R6

Classes

Visão Geral

A linguagem 4D é compatível com o conceito de classes**. Numa linguagem de programação, a utilização de uma classe permite definir um comportamento do objecto com propriedades e funções associadas.

Uma vez que uma classe de usuário é definida, você pode instanciar objetos dessa classe em qualquer lugar do seu código. Cada objecto é uma instância da sua classe. Uma classe pode extend outra classe e herda suas funções e propriedades (declaradas e computadas).

O modelo de classe em 4D é semelhante às classes em JavaScript, e baseado numa cadeia de protótipos.

Por exemplo, você poderia criar uma classe Pessoa com a seguinte definição:

//Class: Person.4dm
Class constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

Function get fullName() -> $fullName : Text
$fullName:=This.firstName+" "+This.lastName

Function sayHello() -> $welcome : Text

$welcome:="Hello "+This.fullName

Ou em um método, criar uma "Pessoa":

var $person : cs. Person //object of Person class  
var $hello : Text
$person:=cs. Person.new("John";"Doe")
// $person:{firstName: "John"; lastName: "Doe" }
$hello:=$person.sayHello() //"Hello John Doe"

Gestão de classes

Definição de classe

Uma classe de usuário em 4D é definida por um arquivo method (.4dm), armazenado na pasta /Project/Sources/Classes/ específico. O nome do arquivo é o nome da classe.

Ao nomear classes, deve ter em mente as seguintes regras:

  • Um nome de classe deve estar em conformidade com as regras de nomenclatura das propriedades.
  • Nomes de classe diferenciam minúsculas de maiúsculas.
  • Não se recomenda dar o mesmo nome a uma classe e a uma tabela de base de dados, a fim de evitar qualquer conflito.

Por exemplo, se quiser definir uma classe chamada "Polígono", precisa criar o seguinte arquivo:

Project folder

Eliminação de uma classe

Para eliminar uma classe existente, pode:

  • no seu disco, remover o arquivo de classe .4dm da pasta "Classes",
  • no Explorador 4D, selecione a classe e clique ou escolha Mover para Lixo no menu contextual.

Using 4D interface

Os arquivos de classe são automaticamente armazenados no local apropriado quando criados através da interface 4D, quer através do menu File, quer através do Explorer.

Você pode criar um novo arquivo de classe para o projeto selecionando Novo > Class... no menu File do 4D Developer ou na barra de ferramentas.

Você também pode usar o atalho Ctrl+Shift+Alt+k.

Explorador

Na página de Métodos do Explorador, as classes são agrupadas na categoria Classes.

Para criar uma nova classe, pode:

  • selecione a categoria Classes e clique no botão .
  • selecione Nova Classe... no menu de ação na parte inferior da janela do Explorer, ou no menu contextual do grupo Classes.
  • selecione Novo > Classe... a partir do menu contextual da página inicial do Explorador.

Suporte de código de classe

Nas várias janelas 4D (editor de código, compilador, depurador, explorador de tempo de execução), o código de classe é basicamente tratado como um método de projecto com algumas especificidades:

  • No editor de código:
    • uma aula não pode ser executada
    • uma função de classe é um bloco de código
    • Ir para a definição em um membro do objeto procura por declarações da classe Função; por exemplo, "$o.f()" encontrará "Função f".
    • Procurar referências na declaração de função da classe procura a função utilizada como membro do objeto; por exemplo, "Função f" irá encontrar "$o.f()".
  • No explorador e Depurador de Runtime, as funções de classe são exibidas com o formato <ClassName> construtor ou <ClassName>.<FunctionName>.

Lojas de classe

As classes disponíveis são acessíveis a partir das suas class stores. Estão disponíveis duas class stores:

  • cs para el class store usuario
  • 4D para el class store integrado

cs

cs : Object

ParâmetroTipoDescrição
classStoreObject<-Class store de usuário para o projeto ou componente

O comando cs devolve a loja de classes de utilizadores para o projecto ou componente actual. Ele retorna todas as classes de usuários definidas no projeto ou componente aberto. Por padrão, apenas as classes ORDA do projeto estão disponíveis.

Exemplo

Se quiser criar uma nova instância de um objecto de myClass:

$instance:=cs.myClass.new()

4D

4D : Object

ParâmetroTipoDescrição
classStoreObject<-Class store 4D

O comando 4D retorna a classe store para as classes 4D incorporadas disponíveis. Ele permite acesso a APIs específicas como CryptoKey.

Exemplo

Se quiser criar uma nova chave na classe CryptoKey:

$key:=4D. CryptoKey.new(New object("type";"ECDSA";"curve";"prime256v1"))

Objecto de classe

Quando uma classe é definida no projeto, ela é carregada no ambiente de linguagem 4D. Uma classe é um objeto em si, da classe "Class" class. Um objecto classe tem as seguintes propriedades e função:

Além disso, um objeto de classe pode fazer referência a um objeto construtor (opcional).

Um objeto de classe em si é um objeto compartilhado e, portanto, pode ser acessado de diferentes processos 4D simultaneamente.

Herança

Se uma classe herda de outra classe (ou seja, a palavra-chave Class extends é usada em sua definição), a classe pai é a sua superclasse.

Quando o 4D não encontra uma função ou uma propriedade em uma classe, ele a procura em sua superclasse; se não for encontrada, o 4D continua procurando na superclasse da superclasse e assim por diante até não haver mais superclasse (todos os objetos herdam da superclasse "Objeto").

Palavras-chave de classe

As palavras-chave 4D específicas podem ser utilizadas nas definições de classes:

  • Função <Name> para definir as funções de classe dos objetos.
  • Construtor da classe para inicializar novos objetos da classe.
  • propriedade para definir as propriedades estáticas dos objetos com um tipo.
  • Função get <Nome> e Função set <Nome> para definir propriedades calculadas dos objetos.
  • Class extends <ClassName> para definir a herança.

Function

Sintaxe

{shared} Function <name>({$parameterName : type; ...}){->$parameterName : type}
// code

As funções de classe são propriedades específicas da classe. Eles são objetos da classe 4D.Function. No arquivo de definição de classe, as declarações de funções usam a palavra-chave Function seguida pelo nome da função.

Se a função for declarada em uma classe compartilhada, você pode usar a palavra-chave shared para que a função possa ser chamada sem Use. .Finalizar estrutura. Para obter mais informações, consulte o parágrafo Shared functions abaixo.

O nome da função deve estar em conformidade com as regras de nomenclatura de objetos.

nota

Como propriedades e funções compartilham o mesmo espaço de nomes, usar o mesmo nome para uma propriedade e uma função da mesma classe não é permitido (um erro é lançado nesse caso).

tip

Dica: Começar o nome da função com um caractere de sublinhado ("_") excluirá a função dos recursos de preenchimento automático no editor de código 4D. Por exemplo, se você declarar Function _myPrivateFunction em MyClass, ela não será proposta no editor de código quando você digitar "cs.MyClass. "`.

Imediatamente seguindo o nome da função, parameters para a função pode ser declarada com um nome e um tipo de dado atribuído, incluindo o parâmetro de retorno (opcional). Por exemplo:

Function computeArea($width : Integer; $height : Integer)->$area : Integer

Dentro de uma função de classe, o comando This é usado como instância de objeto. Por exemplo:

Function setFullname($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

Function getFullname()->$fullname : Text
$fullname:=This.firstName+" "+Uppercase(This.lastName)

Para uma função de classe, o comando Nome do método atual retorna: <NomeDaClasse>.<NomeDaFunção>, por exemplo "MinhaClasse.minhaFunção".

No código da aplicação, as funções de classe são chamadas como métodos membros das instâncias do objeto e podem receber parâmetros se existirem. As seguintes sintaxes são suportadas:

  • utilização do operador (). Por exemplo, myObject.methodName("olá")
  • use of a "4D. Function" class member method:
Aviso de segurança de thread

Se uma função de classe não for thread-safe e for chamada por um método com o atributo "Pode ser executado num processo preemptivo":

  • o compilador não gera qualquer erro (o que é diferente dos métodos normais),
  • um erro é lançado por 4D apenas em tempo de execução.

Parâmetros

Os parâmetros da função são declarados utilizando o nome do parâmetro e o tipo de parâmetro, separados por dois pontos. O nome do parâmetro deve estar em conformidade com as regras de nomenclatura de propriedades. Os parâmetros (e tipos) múltiplos são separados por ponto e vírgula (;).

Function add($x; $y : Variant; $z : Integer; $xy : Object)
nota

Se o tipo não for indicado, o parâmetro será definido como Variant.

Valor retornado

Você declara o parâmetro de retorno (opcional) adicionando uma seta (->) e a definição do parâmetro de retorno após a lista de parâmetro(s) de entrada, ou dois pontos (:) e somente o tipo do parâmetro de retorno. Por exemplo:

Function add($x : Variant; $y : Integer)->$result : Integer
$result:=$x+$y

Você também pode declarar o parâmetro de retorno adicionando apenas : type e usar a return expression (ele também encerrará a execução da função). Por exemplo:

Function add($x : Variant; $y : Integer)-&gt;$result : Integer

Exemplo 1

property name : Text
property height; width : Integer

// Classe: Rectangle
Class constructor($width : Integer; $height : Integer)
This.name:="Rectangle"
This.height:=$height
This.width:=$width

// Definição da função
Function getArea()->$result : Integer
$result:=(This.height)*(This.width)
// In a project method

var $rect : cs. Rectangle
var $area : Real

$rect:=cs. Rectangle.new(50;100)
$area:=$rect.getArea() //5000

Exemplo 2

Este exemplo utiliza a expressão return:

Function getRectArea($width : Integer; $height : Integer) : Integer
If ($width > 0 && $height > 0)
return $width * $height
Else
return 0
End if

Class constructor

Sintaxe

// Class: MyClass
{shared} {singleton} Class Constructor({$parameterName : type; ...})
// code

Uma função construtora de classe aceita parâmetros opcionais e pode ser usada para criar e inicializar objetos da classe de usuário.

Quando você chama a função new(), o construtor da classe é chamado com os parâmetros opcionalmente passados para a função new().

Só pode haver uma função de construtor em uma classe (caso contrário um erro é retornado). Um construtor pode utilizar a palavra-chave Super para chamar o construtor da superclasse.

É possível criar e digitar propriedades de instância dentro do construtor (ver exemplo). Em alternativa, se os valores das propriedades de instância não dependem dos parâmetros passados ao construtor, você pode defini-los usando a palavra-chave property.

Usando a palavra-chave compartilhado cria uma classe compartilhada, usada apenas para instanciar objetos compartilhados. Para obter mais informações, consulte o parágrafo Shared functions abaixo.

Usar a palavra-chave singleton cria um singleton, usado para criar uma única instância. Para obter mais informações, consulte o parágrafo classes do Singleton.

Exemplo

// Class: MyClass
// Class constructor of MyClass Class Constructor ($name : Text)
This.name:=$name
// In a project method
// You can instantiate an object
var $o : cs. MyClass
$o:=cs. MyClass.new("HelloWorld")
// $o = {"name":"HelloWorld"}

propriedade

Sintaxe

property <propertyName>{; <propertyName2>;...}{ : <propertyType>}

A palavra-chave property pode ser utilizada para declarar uma propriedade dentro de uma classe usuário. Uma propriedade de classe tem um nome e um tipo.

A declaração de propriedades de classe melhora as sugestões do editor de código, as funcionalidades de antecipação de tipos e a detecção de erros.

As propriedades são declaradas para novos objetos quando você chama a função new(), no entanto elas não são automaticamente adicionadas aos objetos (elas são adicionadas apenas quando lhes é atribuído um valor).

nota

Uma propriedade é adicionada automaticamente ao objeto quando é inicializado na linha de declaração.

O nome do parâmetro deve estar em conformidade com as regras de nomenclatura de propriedades.

nota

Como propriedades e funções compartilham o mesmo espaço de nomes, usar o mesmo nome para uma propriedade e uma função da mesma classe não é permitido (um erro é lançado nesse caso).

O tipo de propriedade pode ser um dos seguintes tipos suportados:

SintaxeConteúdos
TextValor texto
DateValor data
TimeValor Hora
BooleanValor booleano
IntegerValor inteiro longo
RealValor real
PointerValor ponteiro
PictureValor imagem
BlobValor BLOB
CollectionValor colecção
VariantValor variant
ObjectObject with default class (4D.Object)
4D.<className>Objecto do nome da classe 4D
cs.<className>Objeto do nome da classe usuário
cs.<namespace>.<className>Objeto do nome da classe do componente <namespace>

Se você omitir o tipo na linha de declaração, a propriedade é criada como uma variante.

info

A palavra-chave property só pode ser utilizada em métodos de classe e fora de qualquer bloco Function ou Class Constructor.

Inicializando a propriedade na linha de declaração

Ao declarar uma propriedade, você tem a flexibilidade de especificar seu tipo de dados e fornecer seu valor em uma única instrução. A sintaxe suportada é:

property <propertyName> { : <propertyType>} := <Propertyvalue>

nota

Ao usar essa sintaxe, você não pode declarar várias propriedades na linha de declaração.

Você pode omitir o tipo na linha da declaração, caso em que o tipo será inferido quando possível. Por exemplo:

// Class: MyClass

property name : Text := "Smith"
property age : Integer := 42

property birthDate := !1988-09-29! //data é inferida
property fuzzy //variant

Quando você inicializa uma propriedade em sua linha de declaração, ela é adicionada ao objeto da classe após sua instanciação com a função new(), mas antes que o construtor seja chamado.

Se uma classe estende outra classe, as propriedades da classe pai são instanciadas antes das propriedades da classe filho.

nota

If you initialize a property in its declaration line with an object or a collection in a shared class, the value is automatically transformed into a shared value:

// in a shared class
property myCollection := ["something"]
// myCollection will be a shared collection
// equivalent to:
myCollection := New shared collection("something")

Exemplo

// Class: MyClass

property name : Text
property age : Integer
property color : Text := "Blue"

Num método:

var $o : cs.MyClass
$o:=cs.MyClass.new() //$o:{"color" : "Blue"}
$o.name:="John" //$o:{"color" : "Blue"; "name" : "John"}
$o.age:="Smith" //error com a sintaxe checada

Função get e Function set

Sintaxe

{shared} Function get <name>()->$result : type
// código
{shared} Function set <name>($parameterName : type)
// código

Função obter e Função definir são acessores que definem propriedades computadas na classe. Uma propriedade calculada é uma propriedade nomeada com um tipo de dados que oculta um cálculo. Quando um valor de propriedade computado é acessado, 4D substitui o código do acessor correspondente:

  • quando a propriedade é lida, a função obter é executada,
  • quando a propriedade é escrita, o conjunto de função é executado.

Se a propriedade não for acedida, o código nunca é executado.

As propriedades computadas são concebidas para tratar dados que não precisam de ser guardados na memória. São geralmente baseados em propriedades persistentes. Por exemplo, se um objeto de classe contiver como propriedade persistente o preço bruto e a taxa de IVA, o preço líquido poderia ser tratado por uma propriedade calculada.

No arquivo de definição de classe, as declarações de propriedade computadas usam as palavras-chave Função (a getter) e Function set (as setter), seguido pelo nome da propriedade. O nome deve estar em conformidade com as regras de nomenclatura de propriedades.

A função get devolve um valor do tipo de propriedade e A função set recebe um parâmetro do tipo de propriedade. Ambos os argumentos devem estar em conformidade com os [parâmetros de função] padrão (#parâmetros).

Quando ambas as funções são definidas, a propriedade computada é read-write. Se apenas uma Function get for definida, a propriedade computada será somente leitura. Neste caso, é devolvido um erro se o código tentar modificar a propriedade. Se apenas um Function set estiver definido, 4D devolve undefined quando a propriedade é lida.

Se as funções forem declaradas em uma classe compartilhada, você pode usar a palavra-chave shared com elas para que elas possam ser chamadas sem Use. .Finalizar estrutura. Para obter mais informações, consulte o parágrafo Shared functions abaixo.

O tipo da propriedade calculada é definido pela declaração de tipo $return do getter. Pode ser de qualquer tipo de propriedade válida.

A atribuição de undefined a uma propriedade de objeto apaga seu valor enquanto preserva seu tipo. Para fazer isso, a Function get é chamada primeiro para recuperar o tipo de valor, em seguida, a Function set é chamada com um valor vazio desse tipo.

Exemplo 1

//Class: Person.4dm
property firstName; lastName : Text

Class constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

Function get fullName() -> $fullName : Text
$fullName:=This.firstName+" "+This.lastName

Function set fullName( $fullName : Text )
$p:=Position(" "; $fullName)
This.firstName:=Substring($fullName; 1; $p-1)
This.lastName:=Substring($fullName; $p+1)
//num método projecto
$fullName:=$person.fullName // A função get fullName() é chamada
$person.fullName:="John Smith" // A função set fullName() é chamada

Exemplo 2

Function get fullAddress()->$result : Object

$result:=New object

$result.fullName:=This.fullName
$result.address:=This.address
$result.zipCode:=This.zipCode
$result.city:=This.city
$result.state:=This.state
$result.country:=This.country

Class extends <ClassName>

Sintaxe

// Classe: ChildClass
Classe estende <ParentClass>

A palavra-chave Class extends é usada na declaração de classe para criar uma classe de usuário que é filho de outra classe de usuário. A classe filha herda todas as funções da classe mãe.

A extensão de classe deve respeitar as seguintes regras:

  • Uma classe de usuário não pode estender uma classe embutida (exceto 4D.Object e classes ORDA que são estendidas por padrão para classes de usuário).
  • Uma classe de usuário não pode estender uma classe de usuário de outro projeto ou componente.
  • Uma classe usuário não se pode estender a si própria.
  • Não é possível estender classes de forma circular (ou seja, "a" estende "b" que estende "a").
  • Não é possível definir uma classe de usuário compartilhado estendida de uma classe de usuário não compartilhada.

A violação de uma regra deste tipo não é detectada pelo editor de código ou pelo interpretador, apenas o compilador e check syntax emitirão um erro neste caso.

Uma classe estendida pode chamar o construtor da sua classe pai usando o comando Super.

Exemplo

Este exemplo cria uma classe chamada Square a partir de uma classe chamada Polygon.

//Class: Square

/path: Classes/Square. dm

Classe estende o construtor Polygon

Classe ($side : Integer)

// Ele chama o construtor da classe pai com comprimentos
// fornecido para a largura e a altura
Super($side;$side)
// Em classes derivadas, Super deve ser chamado antes de você
// pode usar 'Isso'
Isso. ame:="Quadrado"



Função getArea() -> $area : Integer
$area:=This.height*This.width

Super

Super( ...param : any )
Super : Object

ParâmetroTipoDescrição
paramany->Parâmetro(s) a passar para o construtor pai
ResultadosObject<-Pai do objecto

A palavra-chave Super permite chamadas à superclasse, ou seja, a classe pai.

Super tem dois objectivos diferentes:

  1. Dentro de um código de construtor, Super é um comando que permite chamar o construtor da superclasse. Quando usado em um construtor, o comando Super aparece sozinho e deve ser usado antes que a palavra-chave This seja usada.
  • Se todos os construtores de classe na árvore de herança não forem correctamente chamados, é gerado o erro -10748. É o programador 4D que se certifica de que as chamadas são válidas.
  • Se o comando This for chamado em um objeto cujas superclasses não foram construídas, o erro -10743 será gerado.
  • Se o Super é chamado fora do escopo do objeto, ou em um objeto cujo construtor de superclasse já foi chamado, erro -10746 é gerado.
// dentro do construtor myClass
var $text1; $text2 : Text
Super($text1) //chama o construtor da superclasse com um parâmetro de texto
This.param:=$text2 // usa o segundo parâmetro
  1. Dentro de uma função de membro da classe, Super designa o protótipo da superclasse e permite chamar uma função da hierarquia da superclasse.
Super.doSomething(42) //chamada a função "doSomething"  
//declarada em superclasses

Exemplo 1

Este exemplo ilustra o uso do Super em um construtor de classe. O comando é chamado para evitar duplicar as partes do construtor que são comuns entre as classes Rectangle e Square.

// Classe: Retângulo
Class constructor($width : Integer; $height : Integer)
Isso. ame:="Retângulo"
Isso.height:=$height
Isso. idth:=$width


Função diz: Name()
ALERT("Oi, eu sou um "+This.name+". )

// Definição de função
função getArea()
var $0 : Integer

$0:=(This.height)*(This.width)
//Classe: Square

Classe extends Rectangle

Construtor da classe ($side : Integer)

// Chama o construtor da classe pai com comprimentos
// fornecidos para a largura e altura do Rectangle
Super($side;$side)
// Em classes derivadas, Super tem de ser chamado antes de
// poder usar 'This'
This.name:="Square"

Function getArea()
C_LONGINT($0)
$0:=This.height*This.width

Exemplo 2

Este exemplo ilustra a utilização de Super em um método de membro da classe. Você criou a classe Rectangle com uma função:

//Classe: Rectângulo

Function nbSides()
var $0 : Text
$0:="I have 4 sides"

Você também criou a classe Square com uma função que chama a função da superclasse:

//Classe: Quadrado

Class extends Rectangle

Function description()
var $0 : Text
$0:=Super.nbSides()+" que são todos iguais"

Depois pode escrever num método projecto:

Parâmetros

This

This : Object

ParâmetroTipoDescrição
ResultadosObject<-Objecto actual

A palavra-chave Isso retorna uma referência ao objeto processado .

Na maioria dos casos, o valor de Isso é determinado pela forma como uma função é chamada. Não pode ser definido por atribuição durante a execução e pode ser diferente de cada vez que a função é chamada.

Quando um formula é chamado como método de membro de um objeto, seu Isso está configurado para o objeto no qual o método é chamado. Por exemplo:

$o:=New object("prop";42;"f";Formula(This.prop))
$val:=$o.f() //42

Quando uma função construtor de classe é usada (com a new()), sua This estará ligada ao novo objeto que está sendo construído.

//Class: ob Class Constructor  

// Create properties on This as
// desired by assigning to them
This.a:=42
// num método 4D  
$o:=cs.ob.new()
$val:=$o.a //42

Quando chamar o construtor da superclasse num construtor utilizando a palavra-chave Super , esteja atento que This não deve ser chamado antes do construtor da superclasse, caso contrário é gerado um erro. Veja este exemplo.

Em qualquer caso, This refere-se ao objeto em que o método foi chamado, como se o método estivesse no objeto.

//Class: ob Function f()
$0:=This.a+This.b

Depois pode escrever num método projecto:

$o:=cs.ob.new()
$o.a:=5
$o.b:=3
$val:=$o.f() //8

Neste exemplo, o objeto atribuído à variável $o não tem sua própria propriedade f, herda-o de sua classe. Uma vez que f é chamado como um método de $o, o seu This refere-se a $o.

Comandos de classe

Vários comandos da linguagem 4D permitem-lhe lidar com funcionalidades de classe.

OB Class

OB Class ( object ) -> Object | Null

OB Class retorna a classe do objeto passada no parâmetro.

OB Instance of

OB Instance of ( object ; class ) -> Boolean

OB Instance de retorna true se object pertence a class ou a uma das suas classes herdadas, e false caso contrário.

Classes compartilhadas

Você pode criar classes compartilhadas. Uma classe compartilhada é uma classe de usuário que instaura um objeto compartilhado quando a função new() é chamada na classe. Uma classe compartilhada só pode criar objetos compartilhados.

Classes compartilhadas também suportam funções compartilhadas que podem ser chamadas sem Use...End use.

O .isShared propriedade de objetos de Classe permite saber se a classe é compartilhada.

info
  • Uma classe inheriting de uma classe não compartilhada não pode ser definida como compartilhada.
  • Classes compartilhadas não são suportadas por classes baseadas em ORDA.

Criação de uma classe compartilhada

Para criar uma classe compartilhada, adicione a palavra-chave shared antes do Construtor de Classe. Por exemplo:

	//shared class: Person
shared Class Constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

//myMethod
var $person := cs.Person.new("John"; "Smith")
OB Is shared($person) // true
cs.Person.isShared //true

Funções compartilhadas

Se uma função definida dentro de uma classe compartilhada modificar objetos da classe, ela deve chamar Use. .Fim de uso estrutura para proteger o acesso aos objetos compartilhados. No entanto, para simplificar o código, você pode definir a função como compartilhada para que ela acione automaticamente o uso interno Use...End use quando executado.

Para criar uma função compartilhada, adicione a palavra-chave shared antes da palavra-chave Function em uma classe compartilhada. Por exemplo:

//classe compartilhada Foo
shared Class Constructor()
This.variable:=1

shared Function Bar($value : Integer)
This.variable:=$value //não é necessário chamar use/end use
nota

Se a palavra-chave da função shared for usada em uma classe de usuário não compartilhada, ela será ignorada.

Classes Singleton

Uma classe singleton é uma classe de usuário que produz apenas uma única instância. Para más información sobre los singletons, por favor consulte la página Wikipedia sobre los singletons. A singleton has a unique instance for the process in which it is instantiated, while a shared singleton has a unique instance for all processes on the machine. Singletons são úteis para definir valores que precisam estar disponíveis em qualquer lugar em um aplicativo ou processo.

A classe singleton é instanciada na primeira chamada da propriedade cs.<class>.me. A classe singleton instanciada é então sempre retornada quando a propriedade me é usada.

Se você precisar instanciar um singleton com parâmetros, você também pode chamar a função new(). Nesse caso, é recomendado instanciar o singleton em algum código executado no início da aplicação.

O .isSingleton propriedade de objetos de classe permite saber se a classe é uma singleton.

Âmbito

The scope of a singleton instance can be the process where it is instantiated or all processes on the machine, depending on its shared property.

Singleton criado emScope if not sharedScope if shared
4D usuário únicoProcessoAplicação
4D ServerProcessoMáquina 4D Server
Modo remoto 4DProcess (nota: os singletons não são sincronizados no processo gêmeo)Máquina remota 4D

Once instantiated, a singleton class (and its singleton) exists as long as a reference to it exists somewhere in the application running on the machine.

info

As classes Singleton não são suportadas por classes baseadas em ORDA.

Criação de um singleton

To create a singleton class, add the singleton keyword before Class Constructor. Por exemplo:

	//class: ProcessTag
singleton Class Constructor()
This.tag:=Random

Para usar o singleton:

	//em um processo
var $mySingleton := cs.ProcessTag.me //Primeira instância
//$mySingleton.tag = 5425 por exemplo
...
var $myOtherSingleton := cs.ProcessTag.me
//$myOtherSingleton.tag = 5425

	//em outro processo
var $mySingleton := cs.ProcessTag.me //Primeira instância
//$mySingleton.tag = 14856 por exemplo
...
var $myOtherSingleton := cs.ProcessTag.me
//$myOtherSingleton.tag = 14856

Criação de um singleton compartilhado

To create a singleton shared by all processes on the machine, add the shared singleton keywords before the Class Constructor. Por exemplo:

//Class VehicleFactory

property vehicleBuilt : Integer

shared singleton Class constructor()
This.vehicleBuilt := 0 //Número de veículos feitos pela fábrica

shared Function buildVehicle ($type : Text) -> $vehicle : cs.Vehicle

Case of
: $type="car"
$vehicle:=cs.Car.new()
: $type="truck"
$vehicle:=cs.Truck.new()
: $type="sport car"
$vehicle:=cs.SportCar.new()
: $type="motorbike"
$vehicle:=cs.Motorbike.new()
Else
$vehicle:=cs.Car.new()
End case
This.vehicleBuilt+=1

You can then call the cs.VehicleFactory singleton to get a new vehicle from everywhere in the application on your machine with a single line:

$vehicle:=cs.VehicleFactory.me.buildVehicle("caminhão")

Como a função buildVehicle() modifica o singleton cs.VehicleFactory (ao incrementar This.vehicleBuilt) você precisa adicionar a palavra-chave shared a ela.

Veja também

Veja também este post de blog para mais detalhes.