Your generic class would look like this:
public class CrudRefeicao<T extends Refeicao> {
public void cadastrar(T refeicao) { /* ... */ }
public void remover(T refeicao) { /* ... */ }
public void editar(T refeicao) { /* ... */ }
public T ler(long id) { /* ... */ }
public void gravar(T refeicao) { /* ... */ }
public T recuperarDados(long id) { /* ... */ }
}
However, I have to warn you that for what you are doing, you probably do not need generic types, so you can do this:
public class CrudRefeicao {
public void cadastrar(Refeicao refeicao) { /* ... */ }
public void remover(Refeicao refeicao) { /* ... */ }
public void editar(Refeicao refeicao) { /* ... */ }
public Refeicao ler(long id) { /* ... */ }
public void gravar(Refeicao refeicao) { /* ... */ }
public Refeicao recuperarDados(long id) { /* ... */ }
}
Or maybe apply generics only to some methods:
public class CrudRefeicao {
public void cadastrar(Refeicao refeicao) { /* ... */ }
public void remover(Refeicao refeicao) { /* ... */ }
public void editar(Refeicao refeicao) { /* ... */ }
public <T extends Refeicao> T ler(Class<T> tipo, long id) { /* ... */ }
public void gravar(Refeicao refeicao) { /* ... */ }
public <T extends Refeicao> T recuperarDados(Class<T> tipo, long id) { /* ... */ }
}
Before implementing a generic class, ask yourself whether generic types will actually add value or just introduce extra complexity. One way to know this is to ask yourself what kind of important type restriction this will bring and what kind of problems the non-use of generics will cause:
-
In the case of java.util.List
it is because it delimits which types of objects can be inserted into or removed from the list, and by not using the generic types, it becomes very easy to pollute lists with types heterogeneous.
-
The case of java.util.Map
is similar to java.util.List
, but with generics independent of keys and values.
In cases of java.util.function
and java.util.List
it is because somewhere in the program, objects are placed inside the collection and then read from it, and generic types serve to bind the type of data inserted to the data type which is read elsewhere, in this order necessarily. Because you're doing a CRUD in a database or something, you eliminate the need to sort the operations and with it might eliminate the need for generic types. In addition, many programs tend to create multiple instances of java.util.Map
and java.util.List
in several different locations and for different purposes. Already in your case, it seems to me that a singleton instance would solve your problem.
In your case, I see little benefit that would be gained by having java.util.Map
as generic. Methods that return CrudRefeicao
could accept any type of void
as a parameter, and here having the generic type restriction would probably bother much more that would help. For the few methods that provide instances of Refeicao
, either you would have to return the supertype anyway, or you could put a parameter that indicates the type you want.
With a T
method and maybe long getId()
in class void setId(long id)
, perhaps overwriting them in subclasses, you probably already eliminate the need to have Refeicao
as a generic class.
Another way of analyzing is to think of whether an instance of CrudRefeicao
has any value, whether it would be usable, or whether it is something completely different from CrudRefeicao<Refeicao>
and CrudRefeicao<Ingrediente>
.
Incidentally, doing CrudRefeicao<Prato>
and Ingrediente extends Refeicao
seems to me to be an inadequate modeling, so this would be a XY problem . In my point of view, the correct thing would be to say that a meal has one or more dishes and not that a meal is a dish. Also, the ingredient is definitely not a meal, but something that is part of a meal.
The Prato extends Refeicao
and consultarRefeicao(Ingrediente)
methods do not seem to make sense, at least not with the modeling you have. The meal in the case would already be the parameter itself passed, and then there would be nothing to be consulted.