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.

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.

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