如何解决Kotlin 中抽象类的实例并在不覆盖的情况下调用抽象函数
我正在做这个谷歌代码实验室android-room-with-a-view-kotlin。这是指向 codelab 的链接。在第 8 步创建房间数据库时,他们使用了此代码
// Annotates class to be a Room Database with a table (entity) of the Word class
@Database(entities = arrayOf(Word::class),version = 1,exportSchema = false)
public abstract class WordRoomDatabase : RoomDatabase() {
abstract fun wordDao(): WordDao
companion object {
// Singleton prevents multiple instances of database opening at the
// same time.
@Volatile
private var INSTANCE: WordRoomDatabase? = null
fun getDatabase(context: Context): WordRoomDatabase {
// if the INSTANCE is not null,then return it,// if it is,then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,WordRoomDatabase::class.java,"word_database"
).build()
INSTANCE = instance
// return instance
instance
}
}
}
}
我想问一下为什么在我创建这个抽象类的一个实例(在 A 类中)然后调用它的抽象 function(getNoteDao)
而不覆盖它的这两行(valexam & val dao)中没有错误.
class A{
val exam : WordRoomDatabase = WordRoomDatabase.getDatabase(application)
val dao = exam.getWordDao()
}
因为我们知道我们需要覆盖 abstract
function
并且不能直接调用它但是那里发生了什么。为什么没有错误
解决方法
exam
行没有错误,因为 getDataBase
是一个“伴随”对象,或者如果您来自 Java 世界,这意味着它是抽象类中的“静态”函数。这意味着
- 伴随对象中的函数(或静态函数)属于类,而不是类的实例
- 您不能在类的实例上调用静态/伴随对象函数,因此请注意,当您调用“WordRoomDatabase.getDatabase...”时,“WordRoomDatabase”的末尾没有括号。您无需创建它的实例即可调用
getDatabase
函数
第 2 行没有错误有点难以发现。
在 getDatabase()
中,您是 Room.dataBaseBuilder(...)
并传入抽象类。在该构建器中,android 实际上创建了抽象 WordRoomDatabase
的实例。类并覆盖您的抽象 wordDao
函数
如果您使用的是 AndroidStudio,请构建您的代码。完成后,WordRoomDatabase
旁边的列上会出现一个指向下方的绿色小箭头。如果您点击它,您将能够看到 Room 生成的覆盖您的抽象函数的类
您不会收到任何错误,因为这些抽象类的实现是由 kapt
在编译时自动生成的。如果您仔细查看您的 build.gradle
文件,那么您会看到它包含表单中的依赖项
kapt 'androidx.room:room-compiler:X.X.X'
这里的 kapt
代表 kotlin 注解处理工具,它处理所有标有某些注解(例如 @Database
或 @Dao
)的 Room 类并生成它们的实现.比如我定义了如下@Dao接口
@Dao
interface WordDao {
@Insert
fun insert(word: Word)
}
和 kapt
在这个类的实现之后生成
public final class WordDao_Impl implements WordDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter<Word> __insertionAdapterOfWord;
public WordDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfWord = new EntityInsertionAdapter<Word>(__db) {
@Override
public String createQuery() {
return "INSERT OR ABORT INTO `Word` (`someId`) VALUES (?)";
}
@Override
public void bind(SupportSQLiteStatement stmt,Word value) {
stmt.bindLong(1,value.getSomeId());
}
};
}
@Override
public void insert(final Word word) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__insertionAdapterOfWord.insert(word);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
}
WordRoomDatabase
也是如此,它的实现也是自动生成的。如果您想查看这些类,您可以随时在 \app\build\generated\source\kapt\debug\yourpackage
中找到它们,它们标有 _Impl 后缀。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。