1

I'm creating generic DAO for my DataNucleus JDO DAOs. Generic DAO will do get, update, delete, create operations and some other generic operations, so those implementations can be just extended in more specific DAOs.

Is it possible to somehow extend generic DAO and have it return correct types when for example get object by id?

User user = userDao.get(userId); // Is this possible when UserDao extends generic DAO ?? userDao should return user of type User instead of object.
newbie
  • 22,918
  • 75
  • 190
  • 297

2 Answers2

3

Yes, it is possible to do this with generics:

public abstract class Dao<T> {
    public T get(String id) { ... }

    ...
}

public class UserDao extends Dao<User> {
    ...
}

UserDao userDao = new UserDao();
User user = userDao.get(userId); //Returns a User

Depending on your needs, Dao<T> can be an abstract base class, or a generic interface (e.g. public interface IDao<T> { ... }

verdesmarald
  • 11,008
  • 2
  • 38
  • 58
  • Whoops I totally missed that this question was tagged java not C#, but the same thing works in both. I've updated the answer to what I *think* is the correct java syntax but I'm rusty and don't have any java stuff on this machine to check. If I made any syntax errors I apologise, I'll correct them when I can! – verdesmarald Sep 24 '12 at 08:52
  • @versesmarald you should prefer composition over inheritance. See my answer. – CKing Sep 24 '12 at 09:02
1

Part of your question has already been answered by verdesmarald. I would like to add one important change in verdesmarald's code

You should prefer composition over inheritance. Instead of extending UserDao from Dao, UserDao should have a Dao. This way, your code will not be bound to a single implementation and mocking the Dao during unit testing will be possible.

CKing
  • 14,153
  • 4
  • 39
  • 77
  • Do you mean that I should add generic dao to UserDao via constructor? Or did I misunderstood what you meant? – newbie Sep 24 '12 at 09:10
  • I disagree - generic DAO is usually an interface with a single implementation. There's no inheritance or composition involved. The advice is good, but not in this context. – duffymo Sep 24 '12 at 09:13
  • @newbie That's right. UserDao should have a Dao instance variable and a constructor that takes a parameter of type Dao. Similarly, every XYZDao class can have a constructor that takes Dao as a parameter. While unit testing, you can pass in a subclass of Dao that simply mocks the database calls by printing a message and returning without any actual database operation. – CKing Sep 24 '12 at 09:16
  • 2
    The point you missed is that there's no need to extend generic DAO to create a User DAO. You just instantiate an instance with the parameterized type set to User. The code with the "extends" above is incorrect. – duffymo Sep 24 '12 at 09:20
  • @duffymo. Makes sense. If there is no need to extend Dao, then I stand corrected. The context matters in this case! My bad! – CKing Sep 24 '12 at 09:22
  • using generics to fool the compiler into accepting your implicit cast to Object as a statically typed entity, is pretty sad. Unfortunately this is where Java lives these days. – deleted_user Sep 24 '12 at 09:23