Download - Javafx Avancado
JavaFX ScriptClasses, binding e outros elementos
Fábio Nogueira de LucenaInstituto de Informática (UFG)Graduação em Engenharia de Softwarehttp://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 1a = 2;println(“{a} {b}”); // 2 2
Binding expressions são automaticamentereavaliadas quando suas dependências mudam
Binding
var a = 1;
var b = bind a+1; // Expressão é ‘a+1’println(“{a} {b}”); // 1 2a = 2;println(“{a} {b}”); // 2 3
Binding expressions são automaticamentereavaliadas quando suas dependências mudam
Binding
var a = 1;var quadrado = bind a*a; println(“{a} {quadrado}”); // 1 1a = 3;println(“{a} {quadrado}”); // 3 9
Binding expressions são automaticamentereavaliadas 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ãoreavaliadas quando suas dependências mudam
O que está acontecendo?
O runtime de JavaFX “sabe” que o valor dea 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!
var a = bind pi * raio * raio;
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ãoreavaliadas 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 passos depende de seq e y
Binding (block)var x = 1;var y = 2;var z = bind { def aux = x + y; 2 * aux;};println(z); // 6y = 1;println(z); // 4x = 0;println(z); // 2
z depende de aux, que depende de x e yOU 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ÊNCIABinding 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); // 4y = 1;println(resultado); // 3k = 0;println(resultado); // 3
O binding de resultado depende de x e yQuando 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); // 4y = 1;println(resultado); // 3k = 0;println(resultado); // 1
O binding de resultado depende de k*x+yQuando 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: aa.nome = "A";println("{a.hashCode()}: {a.nome}"); // hashX: AvarNome = "b";println("{a.hashCode()}: {a.nome}"); // hashY: b
O binding de a depende de varNomeQuando 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: avarNome = "b";println("{a.hashCode()}: {a.nome}"); // hashX: b
O binding de a não depende de varNomeQuando varNome mudar, apenas o valor de
a.nome é alterado.
Binding bidirecional
Binding bidirecional acrescentewith 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-versaQuando a mudar y também mudaQuanto 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árioindicar 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”