Você está na página 1de 29

JavaFX Script

Classes, binding e outros elementos

Fábio Nogueira de Lucena


Instituto de Informática (UFG)
Graduação em Engenharia de Software
http://engenhariadesoftware.inf.br
Visão geral de recursos
“avançados”
Classe
class Aluno {
var nome : String;
var nota : Number;
public override function toString() : String {
“Aluno {nome} ({nota})”;
}
}

println(Aluno { nome: “Fulano” nota: 3 });


println(new Aluno().nota);
Sobrescrever para 1 objeto
class Aluno {
var nome : String;
var nota : Number;
}

var a = Aluno {
nome: “Fulano”
nota: 3
public override function toString() : String {
"Aluno {nome} ({nota})";
}
};

println(new Aluno);
println(a);
Binding:
permite associar variável ao
valor de uma expressão
Binding

var a = 1;
var b = bind a; // Expressão é ‘a’
println(“{a} {b}”); // 1 1
a = 2;
println(“{a} {b}”); // 2 2

Binding expressions são automaticamente


reavaliadas quando suas dependências mudam
Binding

var a = 1;
var b = bind a+1; // Expressão é ‘a+1’
println(“{a} {b}”); // 1 2
a = 2;
println(“{a} {b}”); // 2 3

Binding expressions são automaticamente


reavaliadas quando suas dependências mudam
Binding

var a = 1;
var quadrado = bind a*a;
println(“{a} {quadrado}”); // 1 1
a = 3;
println(“{a} {quadrado}”); // 3 9

Binding expressions são automaticamente


reavaliadas quando suas dependências mudam
Binding
var pi = 3.1415926536;
var raio = 1;
var area = bind pi * raio * raio;
println("Área de círculo de raio {raio}: {area}");
raio = 3;
println("Área de círculo de raio {raio}: {area}");

Lembre-se: binding expressions são


reavaliadas quando suas dependências mudam
O que está acontecendo?
var a = bind pi * raio * raio;

O runtime de JavaFX “sabe” que o valor de


a deve ser atualizado sempre que o valor
da expressão pi * raio * raio for alterado, ou seja,
sempre que pi ou o valor de raio for alterado. Quando
isto ocorre, o runtime reavalia a expressão e o
resultado é depositado na variável a!
Mais um exemplo...
var x = 1;
def dobro = bind 2 * x;
def msg = bind "O dobro de {x} é {dobro}";
println(msg);
x = 2;
println(msg);

Lembre-se: binding expressions são


reavaliadas quando suas dependências mudam
Binding (if)
var pi = 3.1415926536;
var r = 1;
var area = bind if (r <= 0) then 0 else pi*r*r;
println("Área de círculo de raio {r}: {area}");
r = -3;
println("Área de círculo de raio {r}: {area}");

O binding depende, neste exemplo, da condição, do


corpo do then e do else, ou seja, das variáveis r e pi
Binding (if)
var pi = 3.1415926536;
var r = 1;
var area = bind if (r <= 0) then“inválido”else“{pi*r*r}”;
println("Área de círculo de raio {r}: {area}");
r = -3;
println("Área de círculo de raio {r}: {area}");

O binding depende, neste exemplo, da condição, do


corpo do then e do else, ou seja, nas variáveis r e pi
Binding (for)
var fim = 1;
def s = bind for (x in [1..fim]) x*x+10;
println(s); // [ 11 ]
fim = 2;
println(s); // [ 11 14 ]

O binding depende apenas da variável fim


Binding (for)
var fim = 1;
var passo = 1;
var y = 3;
var seq = bind [1..fim step passo];
def s = bind for (x in seq where x<y) x;
println(s); // [ 1 ]
fim = 2;
println(s); // [ 1 2 ]
passo = 2;
println(s); // [ 1 ]
y = -1;
println(s); // [ ]

seq depende de fim e de passo


s depende de seq e y
Binding (block)
var x = 1;
var y = 2;
var z = bind {
def aux = x + y;
2 * aux;
};
println(z); // 6
y = 1;
println(z); // 4
x = 0;
println(z); // 2

z depende de aux, que depende de x e y


OU SEJA, z depende de x e y
Binding (function)
Pode existir binding para uma função
A função pode ser non-bound ou bound

DEPENDÊNCIA
Binding para non-bound function: argumentos
Binding para bound function: bloco
Binding (non-bound function)
var k : Integer = 2;
function fazAlgo(x : Integer, y : Integer) {
k * x + y;
}
var x = 1;
var y = 2;
var resultado = bind fazAlgo(x,y);

println(resultado); // 4
y = 1;
println(resultado); // 3
k = 0;
println(resultado); // 3

O binding de resultado depende de x e y


Quando x ou y mudar, fazAlgo é executada e o valor
obtido é depositado em resultado
Binding (bound function)
var k : Integer = 2;
bound function fazAlgo(x : Integer, y : Integer) {
k * x + y;
}
var x = 1;
var y = 2;
var resultado = bind fazAlgo(x,y);

println(resultado); // 4
y = 1;
println(resultado); // 3
k = 0;
println(resultado); // 1

O binding de resultado depende de k*x+y


Quando x ou y ou k mudar, fazAlgo é executada e o
valor obtido depositado em resultado
Binding (object literal)
Variável com binding para object literal depende da união
das dependências de todas as expressões do lado direito
das variáveis de instância.

Não inclui dependências de variáveis de instâncias


para as quais há binding.

Quando ocorre mudança, cria-se uma


nova instância!
Binding (object literal)
class Aluno {
var nome: String;
}

var varNome = "a";

var a = bind Aluno { nome: varNome };

println("{a.hashCode()}: {a.nome}"); // hashX: a


a.nome = "A";
println("{a.hashCode()}: {a.nome}"); // hashX: A
varNome = "b";
println("{a.hashCode()}: {a.nome}"); // hashY: b

O binding de a depende de varNome


Quando varNome mudar, uma nova instância é
criada e passa a ser referenciada por a
Binding (object literal)
class Aluno {
var nome: String;
}

var varNome = "a";

var a = bind Aluno { nome: bind varNome };

println("{a.hashCode()}: {a.nome}"); // hashX: a


varNome = "b";
println("{a.hashCode()}: {a.nome}"); // hashX: b

O binding de a não depende de varNome


Quando varNome mudar, apenas o valor de
a.nome é alterado.
Binding bidirecional

Binding bidirecional acrescente


with inverse
ao final da expressão envolvendo o binding
Binding bidirecional

var x = 10;
var y = bind x with inverse;
println("x: {x} y: {y}");
x = 2;
println("x: {x} y: {y}");
y = 5;
println("x: {x} y: {y}");

O binding de y depende de a e vice-versa


Quando a mudar y também muda
Quanto y mudar a também muda
Variável (function)
var operacao : function(:Byte, :Byte) : Byte;
var add = function(x:Byte, y:Byte) { x + y };
var sub = function(x:Byte, y:Byte) { x - y };
var pro = function(x:Byte, y:Byte) { x * y };
var div = function(x:Byte, y:Byte) { x / y };

var ops = [ add, sub, pro, div ];

for (op in ops) {


println(op(10,2));
}

Qual o resultado?
Variável (function)
var f : function(:Boolean):function(x:Byte,y:Byte):Byte;
var add = function(x:Byte,y:Byte) { x + y };
var sub = function(x:Byte,y:Byte) { x - y };

f = function(flag : Boolean) {
if (flag) add else sub
};

println(f(true)(1,2));
println(f(false)(1,2));

Qual o resultado?
Variável (function)

var add = function(x:Byte,y:Byte) { x + y };


var sub = function(x:Byte,y:Byte) { x - y };

var f = function(flag : Boolean) {


if (flag) add else sub
};

println(f(true)(1,2));
println(f(false)(1,2));

Inferência de tipos tornou desnecessário


indicar o tipo da variável f, ao contrário do
exemplo anterior (tipo explicitado)
Triggers

var x = 10 on replace antigo {


println("x mudou de {antigo} para {x}");
};

x = 11;
x = 30;
Considerações finais
Nem tudo de JavaFX foi abordado
Tratamento de exceções
Classes (herança múltipla, init, postinit, ...)
Organização do código em packages, classes,...
Modificadores de acesso: public-init, public-read, ...
Visão geral é suficiente para “aprofundar”

Você também pode gostar