2016-10-28 10 views
3

Обычно я пытаюсь использовать полиморфизм, чтобы избежать использования таких вещей, как instanceof, и мне не нравится использование фреймворков ORM, потому что они часто вызывают у меня гораздо больше головной боли, поэтому я попытался создать собственный класс базы данных с простыми функциями.Как вызывать определенные методы и возвращать определенные объекты на основе типа класса

Некоторые из вас, вероятно, хихикают: «Смотрите, ORM существуют по какой-то причине, не катитесь!» но я не пытаюсь сделать полномасштабную ORM; просто что-то легкое для моего конкретного использования, которое делает то, что мне нужно (см. более хихикание, я знаю).

Сейчас я ударяя этот вопрос:

Обычно при выполнении оператора выбора из SQLiteDatabase при создании объектов из таблиц данных, вы используете Cursor объект, перебирать записи, а также создать экземпляр объекта в петля.

Рассмотрите класс Dog, который расширяет MyDatabaseClass.

Это считается плохой практикой, чтобы сделать что-то вроде этого:

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; 
} 

}

Так что теперь, если я хочу, чтобы получить список собак я могу сделать

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

или сделать это статический метод класса Dog, если это необходимо.

Рассматривается ли это действительный подход или считается опасным для сравнения такого класса? Мне бы очень хотелось использовать полиморфизм, но я не мог найти никакого хорошего способа сделать это из-за наличия разных полей для разных классов с разными конструкторами.

+0

Исправлено несколько опечаток – user7086932

+0

С чем вы пытаетесь это сделать - это прекрасно. Это то, что делают все инструменты orm - преобразование общего набора результатов в определенный набор объектов. Единственное отличие заключается в том, что отображение вытеснено в каком-либо файле xml, или аннотация заботится об этом. – donlys

ответ

1

Если вы укажете тип данных, вы можете использовать дженерики.

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; 
    } 
+0

Что это позволяет мне делать то, что мой текущий код не делает? Избегайте кастинга позже? edit: После попытки этого он не компилируется. Ему не нравится строка, в которую объект добавляется в список. Я даже попытался изменить метод getDatabaseObject, чтобы использовать , но ничего. – user7086932

+0

Должен ли я изменить метод getDatabseObject на нечто вроде 'public T getDatabaseObject (класс clazz, курсорный курсор) {if (clazz == Dog.class) return (T) getDogFromCursor (курсор); } '? – user7086932

+0

Вам не нужно изменять 'getDatabaseObjectFromCursor()', так как он возвращает 'MyDatabaseClass'. – Paulo

0

Как об этом будет выглядеть следующим образом:

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

его гораздо лучше, чем if (clazz == Dog.class) и вы можете использовать полиморфизм, имеющий некоторое BaseRepository с обычными методами.

+0

Что будет внутри DogRepository точно? Мне бы хотелось, чтобы getList() был частью BaseRepository. Будет ли у DogRepository только такие вещи, как getDogCursor и т. Д.? – user7086932

+0

BaseRepository может иметь абстрактный 'getItemFromCursor', а DogRepository должен реализовывать его, как вы это делаете в' getDogFromCursor' – lamik

+0

То же самое для 'getItemCursor' - метод базового вызова с параметрами' Dog.TABLE' и 'Dog.COLS'. Или объявите абстрактные методы 'getTableName' и' getColumnNames' и реализуйте их в DogRepository – lamik