微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Kotlin 中抽象类的实例并在不覆盖的情况下调用抽象函数

如何解决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 举报,一经查实,本站将立刻删除。