user7086932 user7086932 - 1 month ago 6
Java Question

How to call certain methods and return certain objects based on class type

Normally I try to use polymorphism to avoid using things like

instanceof
, and I don't like using ORM frameworks because they often cause me a lot more headache than they're worth, so I tried to make my own database class with simple features.

Some of you are probably giggling, "See, ORMs exist for a reason, don't roll your own!" but I'm not trying to make a full-blown ORM; just something lightweight for my specific use that does what I need (cue more giggling, I know).

Right now I am hitting this issue:

Normally when doing a select statement from an SQLiteDatabase when creating objects from the data tables, you use a
Cursor
object, iterate over the records, and instantiate an object in the loop.

Consider a Dog class that extends MyDatabaseClass.

Is it considered bad practice to do something like this:

public Cursor getDogCursor(Cursor cursor) {
return database.query(Dog.TABLE_NAME, Dog.COLS, null, null, null, null, null);
}

public Cursor getCursor(Class<? extends MyDatabaseClass>) {
if (clazz == Dog.class) return getDogCursor();
//...
return null;
}

public Dog getDogFromCursor(Cursor cursor) {
String dogId = getLongFromColumnName(cursor, Dog._ID);
String dogName = getStringFromColumnName(cursor, Dog.COL_NAME);
return new Dog(dogId, dogName);
}

public MyDatabaseClass getDatabaseObjectFromCursor(Class<? extends MyDatabaseClass> clazz, Cursor cursor) {
if (clazz == Dog.class) return getDogFromCursor(cursor);
//...
return null;
}

public List<? extends MyDatabaseClass> getList(Class<? extends MyDatabaseClass> clazz) {
Cursor cursor = getCursor(clazz);
List<MyDatabaseClass> list = new ArrayList<>();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(getDatabaseObjectFromCursor(clazz, cursor);
cursor.moveToNext();
}
cursor.close();
return list;
}


}

So now if I want to get a list of Dogs I can do

List<Dog> dogList = (List<Dog>) myDatabaseInstance.getList(Dog.class);


or make it a static method of the Dog class if need be.

Is this considered a valid approach, or is it considered dangerous to do that class comparison like this? I would have loved to use polymorphism somehow but I couldn't see any good way to do it on account of there being different fields for different classes with different constructors.

Answer

if you supply the data type, you can use generics.

    public <T extends MyDatabaseClass> List<T> getList(Class<T> clazz) {
        Cursor cursor = getCursor(clazz);
        List<T> list = new ArrayList<>();
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            //noinspection unchecked
            list.add((T) getDatabaseObjectFromCursor(clazz, cursor));
            cursor.moveToNext();
        }
        cursor.close();
        return list;
    }