In short I would define it as follows: badly done class project :), the constructor argument of Menu
should also be typed, since BdApp
is a raw type , which could be a reference to IDAO
, not BdApp
. >
Why did not he instantiate soon doing so: private BdApp<Contato> bd = new BdApp<Contato>();
?
As this code is, it really does not make much difference in initializing the declaration or constructor, one way or another in the end it will only make sense to assign BdApp<Contato>
or attribute bd
to Menu
not depend in anything generic (which leads us to think that it did not have to be generic). For example:
final BdApp<Integer> bd = new BdApp<>();
final Menu menu = new Menu(bd);
menu.listar();
This example compiles and runs smoothly, but it does not make sense to how the class project is. As it stands, the attribute is typed ( private BdApp<Contato> bd
), so even when building an instance of Menu
I tried to change the type of the generic could have problems, as it was later used in the code. p>
In addition, the advantage of having assignment by constructor, setter , etc. is that the instance defines the concrete type, to be able to exchange implementations, to change implementation in runtime (with setter , for example), etc.
However this is quite common, see the example below:
public abstract class Menu<T> {
private final IDAO<T> bd;
public Menu(final IDAO<T> bd) {
this.bd = bd;
}
public void cadastrar() {
try(final Scanner sc = new Scanner(System.in)) {
bd.add(this.instance(sc));
}
}
protected abstract T instance(final Scanner sc);
public void listar() {
final List<T> lista = bd.listar();
for (final T t : lista) {
this.imprimir(t);;
}
}
protected abstract void imprimir(final T t);
}
public class MenuContato extends Menu<Contato> {
public MenuContato(final IDAO<Contato> bd) {
super(bd);
}
@Override
protected Contato instance(final Scanner sc) {
final Contato contato = new Contato();
System.out.print("Digite o nome: ");
contato.setNome(sc.next());
System.out.print("Digite o cpf: ");
contato.setCpf(sc.next());
return contato;
}
@Override
protected void imprimir(final Contato t) {
System.out.println(t.getNome());
}
}
See that we make Menu
generic as well, so we could have Menu anything. In addition to this (and one of the better parts of this) is that we can change the implementation of IDAO
, as stated above. That is, we can pass an instance that saves the data in a list, one that uses persistence in BD, etc., without having to change anything at all.
And if it were not for the parameterized class would the composition look like this?
Yes, if it is not a generic type, it would not be able to parameterize it, so it would be as you observed it, only private BdApp bd
;
Probably this code is not yours, but follow some observations, in addition to the points previously mentioned:
- Always consider having the reference not for the concrete type, but for the interface, this gives you more flexibility. That is,
private BdApp<Contato> bd = new BdApp<>();
instead of private BdApp<Contato> bd = new BdApp<Contato>();
, private List<T> lst = new ArrayList<>();
instead of ArrayList<T> lst = new ArrayList<T>();
and so on. See more ;
- from Java 7 there is diamond operator , then you do not need to qualify the concrete type when instantiating the object, it will be inferred by the reference, ie
private List<T> lst = new ArrayList<>();
and not private List<T> lst = new ArrayList<T>();
;
I quoted a smells of the code just to notice how much it looks like it's in trouble = )