Objectivos
- Aplicação dos conhecimentos adquiridos sobre a Fénix Framework para a especificação do modelo de domínio do projecto utilizando a DML.
- DML e herança
- Apoio ao projecto
Descrição
Este aula serve como apoio à 1ª entrega do projecto de Engenharia de Software. Os alunos já devem estar familiarizados com a especificação do modelo de domínio utilizando a DML providenciada pela Fénix Framework. A aula serve ainda pra ver o impacto da DML na herança entre entidades pertencentes ao domínio da aplicação.
Nota:
cada grupo deverá reunir-se antes da aula de laboratório para desenvolver o máximo possível da implementação da 1ª entrega do projecto para que o docente das práticas possa esclarecer eventuais dúvidas. O apoio dado a cada grupo será com base naquilo que for apresentado durante a aula. Esta aula funciona como uma pré-avaliação do código já realizado.
Herança na DML da Fénix Framework
Se quisermos modelar duas classes Fruta e Abacaxi, que representam entidades que devem pertencer ao estado persistente de uma dada aplicação e que estão relacionadas por uma relação de herança, a forma de o fazer usando a DML da Fénix Framework é a seguinte:
// ficheiro frutaria.dml
class Fruta {
String cor;
float peso;
}
class Abacaxi extends Fruta {
String origem;
}
Note-se que existe uma classe intermédia na relação de herança entre Fruta e Abacaxi.
Na Fénix Framework, cada entidade declarada na DML herda de uma class _Base.
Ou seja, neste caso, a classe Fruta herda de Fruta_Base:
// Ficheiro Fruta.java
public abstract class Fruta extends Fruta_Base {
protected Fruta() {
super();
}
// restantes métodos de Fruta
}E a classe Abacaxi de Abacaxi_Base:
// Ficheiro Abacaxi.java
public class Abacaxi extends Abacaxi_Base {
public Abacaxi() {
super();
}
// restantes métodos de Abacaxi
}A relação de herança entre Abacaxi e Fruta expressa no ficheiro 'frutaria.dml', é obtida através da herança de Abacaxi_Base de Fruta:
// Ficheiro Abacaxi_Base.java gerado automaticamente para build/src
public abstract class Abacaxi_Base extends Fruta {
protected Abacaxi_Base() {
super();
}
// restante código gerado automaticamente pela Fénix Framework
}
O problema é que no construtor de Abacaxi, as referências a possíveis construtores da super classe (via super) referem-se à classe Abacaxi_Base e não a Fruta, como seria desejável. As classes _Base apenas disponibilizam um construtor, o construtor sem argumentos. Dado que estas classes são geradas automaticamente pela Fénix Framework, durante o processamento do ficheiro dml que contém a especificação do modelo do domínio da aplicação. não se deve alterar o código destas classes dado que os ficheiros que contém as classes _Base são destruídos durante o processamento do ficheiro dml.
Uma forma de ter um mecanismo semelhante ao da herança para os construtores, é definir o código de inicialização não no construtor mas num método auxiliar (por exemplo init).
Nesse caso, a classe Fruta passa a ter esse método:
// Ficheiro Fruta.java
public abstract class Fruta extends Fruta_Base {
protected Fruta() {}
protected void init(String cor, float peso) {
setCor(cor);
setPeso(peso);
}
// restantes métodos de Fruta
}
E as classes derivadas como Abacaxi passam a:
// Ficheiro Abacaxi.java
class Abacaxi extends Abacaxi_Base {
public Abacaxi() {
super();
}
public Abacaxi(String origem, float peso) {
super();
init(origem, peso);
}
// permite que a hierarquia de classes possa continuar a crescer
protected void init(String origem, float peso) {
super.init("Yellow", peso);
setOrigem(origem);
}
// restantes métodos de Abacaxi.
}
Desta forma, para se criar uma instância da classe Abacaxi faz-se:
Abacaxi a = new Abacaxi("Azores", 10.0f);Code highlight generated with tohtml.com/java