android—kotlin中抽象类的示例,并在不重写的情况下调用抽象函数

zdwk9cvp  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(459)

我正在做谷歌代码实验室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
            }
        }
   }
}

我想问一下为什么在这两行(val-exam和val-dao)中没有错误,在这两行中我创建了这个抽象类的一个示例(在类a中),然后调用它的抽象类 function(getNoteDao) 没有覆盖它。

class A{

val exam : WordRoomDatabase = WordRoomDatabase.getDatabase(application) 
val dao = exam.getWordDao()
}

因为我们知道我们需要覆盖
abstract function 不能直接称之为,但那里发生了什么。为什么没有错误

t3irkdon

t3irkdon1#

您不会得到任何错误,因为这些抽象类的实现是由 kapt 在编译时。如果你仔细看你的眼睛 build.gradle 文件,然后您将看到它在表单中包含一个依赖项

kapt 'androidx.room:room-compiler:X.X.X'

在这里 kapt 代表kotlin annotation processing tool,它处理标记有特定注解的所有房间类,例如 @Database@Dao 并生成它们的实现。例如,我定义了以下@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后缀标记。

p4tfgftt

p4tfgftt2#

屏幕上没有错误 exam 因为 getDataBase 是一个“同伴”对象,或者如果您来自java世界,这意味着它是抽象类中的一个“静态”函数。这意味着
伴随对象中的函数(或者静态函数)属于类,而不是类的示例
您不能在类的示例上调用静态/伴随对象函数,因此请注意,当您调用“wordroomdatabase.getdatabase…”时,“wordroomdatabase”的末尾没有括号。您不需要创建它的示例来调用 getDatabase 功能
第2行中没有错误,但要发现它有点棘手。里面 getDatabase() 你是 Room.dataBaseBuilder(...) 并传入抽象类。在构建器内部,android实际上创建了抽象的示例 WordRoomDatabase . 类并重写您的摘要 wordDao 功能
如果您使用的是androidstudio,请构建代码。完成后,将有一个绿色的小箭头指向旁边的列 WordRoomDatabase . 如果单击它,您将能够看到room生成的覆盖抽象函数的类

相关问题