TL++ — O que muda?

Daniel Mendes
TOTVS Developers
Published in
3 min readOct 9, 2019

A linguagem TL++ (TOTVS Language Plus Plus) é a evolução do nosso querido AdvPl, mas… O que muda?

Extensão

Para trabalhar com TL++ você precisa criar o seu código fonte com a extensão tlpp, abandonando então nossos prw, prg e prx. Exemplo:

fonte_financeiro.tlpp

Tipagem

Apesar de não ser uma novidade na linguagem, agora a tipagem permite gerar exceções e não somente warnings.

Não é uma novidade? Não… É possível tipar já há alguns anos, acredito que desde o lançamento do Protheus 12.

E quais são os tipos? Os básicos são os seguintes:

  • char
  • logical
  • block
  • number
  • array
  • object
  • date

Nomes?

Essa acho que é a parte que eu mais amei… Com TL++ não existe mais a limitação de dez (10) caracteres para variáveis, funções etc! Sim, isso me faz lacrimejar… Mas enfim, agora a limitação é de 255 caracteres, portanto eu posso criar uma função da seguinte forma:

#include "protheus.ch"
user function essaEhUmaFuncaoEmTLPPComNomeLongo()
local cTestandoNomesLongosEmTLPP as char

cTestandoNomesLongosEmTLPP := "Testando…"
ConOut(cTestandoNomesLongosEmTLPP)return nil

Método Estático

Também não é uma novidade… Mas, o Advpl e também o TL++ permitem a criação de métodos estáticos, que por padrão são públicos:

#include "protheus.ch"
class ClasseComMetodoEstatico
static method metodoEstaticoDaClasse()
endclass

method metodoEstaticoDaClasse() class ClasseComMetodoEstatico
return "Retorno do método estático"

user function testStaticMethod()
ConOut( ClasseComMetodoEstatico():metodoEstaticoDaClasse() )
return nil

Namespace

É, agora temos namespace, permitindo uma organização muito melhor do código!

Para user é simples, basta declarar a namespace:

#include "protheus.ch"
namespace testandonamespace

user function testando_Name_Space()
return "Ok"

E para consumir, existem duas formas:

Usando o nome da namespace antes da função:

#include "protheus.ch"
user function callNameSpaceFunction()
ConOut( testandonamespace.U_testando_Name_Space() )
return nil

Ou, utilizando da namespace no fonte:

#include "protheus.ch"
using namespace testandonamespace

user function callNameSpaceFunction()
ConOut( U_testando_Name_Space() )
return nil

Encapsulamento

Bem, também já disponível desde o AdvPl, temos a opção de escopo para nossos métodos e propriedades, sendo eles:

  • private
  • protected
  • public

Exemplo:

#include "protheus.ch"
class ClasseComEscopo
private data nTeste as numeric
public data cTeste as char
public method new()
public method getTeste()
endclass
method new() class ClasseComEscopo
return

method getTeste() class ClasseComEscopo
return self:cTeste

user function testandoClasseComEscopo()
local oClass as object
oClass := ClasseComEscopo():New()ConOut( oClass:cTeste ) //Público
ConOut( oClass:getTeste() ) //Retorna o propriedade privada
FreeObj( oClass )return nil

JSON

Agora temos um facilitador para a criação de JSON, veja só:

#include "protheus.ch"
user function testandoJSON_TLPP()
local jJson

jJson := { "id": "xisto", "values": { "name": "Daniel", "obs": "DEV" } }
ConOut( jJson["id"] )
ConOut( jJson["values"]["name"] )
ConOut( jJson["values"]["obs"] )
return nil

Interface

Agora temos também o recuso de interface:

#include "protheus.ch"
interface MinhaInterface
method testando()
endinterface

class UsandoInterface extends MinhaInterface
endclass

Nesse exemplo, como eu não implementei o método testando, será gerado um erro de compilação! =)

Obs.: É possível criar a interface em includes!

Sobrecarga de operadores

O que é isso? Bem, é a possibilidade de sobrecarregar as operações de soma, subtração, multiplicação, divisão, igualdade e por fim a conversão para string, ou seja, você consegue criar uma classe com métodos de soma… E a parte que eu mais gosto, se eu fizer a sobrecarga da conversão para string e ao fazer um conout do meu objeto, ele será exibido da forma que eu criei:

#include "protheus.ch"
class ClassToString
data nome as char
data sobrenome as char
method new() constructor
endclass

method new(cNome, cSobrenome) class ClassToString
return self

operator ToString() class ClassToString
return "Nome completo: " + self:nome + " " + self:sobrenome
user function testandoSobrecargaToString()
local oClassToString as object
oClassToString := ClassToString():New("Daniel", "Mendes")
ConOut(oClassToString)
return nil

O que mais?

Existe agora também o recuso de Reflection e Annotation!

Documentação:

--

--