Interfaces e classes concretas

Pessoal, estou com uma duvida …

peguei uma implementação aqui da seguinte forma,

interface Table {

int getNumberOfColumns();
Collection<Column> getColumns();
Column getColumn(String name);

// ... continua ...

}
class ConcreteTable implements Table {

//... atributos

// implementação dos metodos da interface


// sets

public setColumns(Collection<Column> columns) {
// ...
}

}

Eu entendo que da forma como esta a interface, eu garanto de certa forma o encapsulamento, já que publico apenas o que deve ser visivel para classes interessadas na minha inteface, porem, existe o problema de inicializar os atributos da minha classe concreta, o que eu faria atraves de um construtor. Hoje isso é feito pelos sets contidos nas classes concretas. O problema é que para fazer isso, ao inves de utilizar a interface, utiliza-se a classe concreta por todo código como referencia.

Fica as pergunta, pra que existe a interface se todo restante do código utiliza referencia a classe concreta?

Considerando que quem vai utilizar meu codigo só se interesse pela interface, a implementação estaria correta, porem se eu precisar mudar algo internamente, como criar uma nova implementacao de Table, teria problemas?

Colocar os sets na interface seria uma solução na opiniao de voces?

nao sei se expressei claramente minha duvida,

conto com a colaboração de todos,

[]s

nesse caso eu colocaria os métodos na interface…

Pensando bem, acho que entendi o que foi feito …
Eu ofereço serviços por uma interface padrao, mas na implementação interna, faço referencia a classe concreta para manipular os dados livremente.

A pergunta ainda continua a respeito das dificuldades de manutenção no codigo …

[]s

Você pode se utilizar de factories e centralizar a criação de seu objeto concreto em um lugar apenas ao invés de fazer referência no código todo.

Se vc faz referencias a classe concreta tem algo de errado na sua abordagem. Se vc esta utilizando algo da classe concreta de duas uma, ou a interface esta incompleta ou voce nao esta usando a interface, mas a classe concreta, e esta tentando faze-la caber na interface, só que ela nao cabe.

E preciso ver no seu problema qual dos dois casos esta acontecendo.

[quote=YvGa]Se vc faz referencias a classe concreta tem algo de errado na sua abordagem. Se vc esta utilizando algo da classe concreta de duas uma, ou a interface esta incompleta ou voce nao esta usando a interface, mas a classe concreta, e esta tentando faze-la caber na interface, só que ela nao cabe.

E preciso ver no seu problema qual dos dois casos esta acontecendo.[/quote]

vamo dar um exemplo mais concreto … eis o código

public interface Table
  extends DatabaseObject
{

  /**
   * Gets the list of check constraints.
   * 
   * @return Check constraints for the table
   */
  CheckConstraint[] getCheckConstraints();

  /**
   * Gets a column by name.
   * 
   * @param name
   *        Name
   * @return Column.
   */
  Column getColumn(String name);

  /**
   * Gets the list of columns in ordinal order.
   * 
   * @return Columns of the table
   */
  Column[] getColumns();

  /**
   * Gets a comma-separated list of columns.
   * 
   * @return Comma-separated list of columns
   */
  String getColumnsListAsString();

  /**
   * Gets a foreign key by name.
   * 
   * @param name
   *        Name
   * @return ForeignKey.
   */
  ForeignKey getForeignKey(String name);

[code]
class MutableTable
extends AbstractDatabaseObject
implements Table
{

private static final long serialVersionUID = 3257290248802284852L;

private TableType type;
private PrimaryKey primaryKey;
private final NamedObjectList columns = new NamedObjectList(NamedObjectSort.natural);
private final NamedObjectList foreignKeys = new NamedObjectList(NamedObjectSort.natural);
private final NamedObjectList indices = new NamedObjectList(NamedObjectSort.natural);
private final NamedObjectList checkConstraints = new NamedObjectList(NamedObjectSort.natural);
private final NamedObjectList triggers = new NamedObjectList(NamedObjectSort.natural);
private final NamedObjectList privileges = new NamedObjectList(NamedObjectSort.natural);

MutableTable(final String catalogName,
final String schemaName,
final String name)
{
super(catalogName, schemaName, name);
// Default values
type = TableType.unknown;
}

//… restante dos metodos da interface

//… end

// metodos que nao estao na interface e somente na classe concreta

void addCheckConstraint(final MutableCheckConstraint checkConstraint)
{
checkConstraints.add(checkConstraint);
}

void addColumn(final MutableColumn column)
{
columns.add(column);
}

void addForeignKey(final MutableForeignKey foreignKey)
{
foreignKeys.add(foreignKey);
}

//… metodos sets que nao estao na interface

void setCheckConstraintComparator(final NamedObjectSort comparator)
{
checkConstraints.setSortOrder(comparator);
}

void setColumnComparator(final NamedObjectSort comparator)
{
columns.setSortOrder(comparator);
}

void setForeignKeyComparator(final NamedObjectSort comparator)
{
foreignKeys.setSortOrder(comparator);
}

void setIndexComparator(final NamedObjectSort comparator)
{
indices.setSortOrder(comparator);
}

void setPrimaryKey(final PrimaryKey primaryKey)
{
this.primaryKey = primaryKey;
}

void setTriggerComparator(final NamedObjectSort comparator)
{
triggers.setSortOrder(comparator);
}

void setType(final TableType type)
{
if (type == null)
{
throw new IllegalArgumentException(“Null table type”);
}
this.type = type;
}[/code]

Acho que a intencão de quem desenvolveu esta api era que pela interface o usuario tivesse acesso a somente algumas informaçoes (encapsulamento). Mas o que achei estranho é que internamente as classes concretas nao fazem referencia a interfaces. como abaixo …

void addForeignKey(final MutableForeignKey foreignKey) { foreignKeys.add(foreignKey); }

Na minha visao, o correto seria usar a interface ForeginKey como parametro e nao MutableForeignKey.

Entendo que o metodo acima nao esta na interface pq o desenvolvedor nao quis que o usuário conseguisse adicionar uma foreignkey quando recebesse um objeto Table, mas n compreendi o pq nao usou-se a interface como tipo do parametro.

O que fazer, colocar o metodo na interface? essa implementação esta conceitualmente correta? como inicializar os parametros usando uma interface limpa!?

[]s

Na minha opiniao foi mal projetada a interface, ele deveria conter os metodo addForeignKey ect… e recebendo a interface como parametros.

Se vc nao tem acesso e nao vai poder mudar a interface, prepare-se pra ter dor de cabeca na hora de usar, ou nao use a interface pq ele so vai gerar mais trabalho, visto que vc vai ter que fazer casting e testar o tipo de qualquer forma, entao esqueca a interface e use as classes concretas.

Se voce pode alterar a interface nao pense duas vezes.

Essa é minha humilde opiniao, outras podem ser divergentes.

[quote=YvGa]Na minha opiniao foi mal projetada a interface, ele deveria conter os metodo addForeignKey ect… e recebendo a interface como parametros.

Se vc nao tem acesso e nao vai poder mudar a interface, prepare-se pra ter dor de cabeca na hora de usar, ou nao use a interface pq ele so vai gerar mais trabalho, visto que vc vai ter que fazer casting e testar o tipo de qualquer forma, entao esqueca a interface e use as classes concretas.

Se voce pode alterar a interface nao pense duas vezes.

Essa é minha humilde opiniao, outras podem ser divergentes.[/quote]

na verdade, estou contruindo alguma emcima dessa código, que pertence a uma API, a qual nao posso alterar o código fonte.

Vamos supor que quem utilize a interface nao possa adicionar uma chave estrangeira, se eu publicar esse método an interface estaria fazendo algo errado, entao coloco aonde?

eu entendo seu ponto de vista … mas continuo em duvida …

[]s

acho que enconctrei a solução para o meu problema …

http://www.guj.com.br/posts/list/23735.java (Pagina 5)

[…]s