Я не могу решить, казалось бы, тривиальную проблему. Моя проблема, вероятно, заключается в отсутствии у меня опыта (и понимания) языка котлин. Тем не менее, мне понадобится помощь с этим.
Я создал собственный класс, содержащий пользовательскую функцию. Это кажется достаточно простым, но я продолжаю получать ошибку «неразрешенная ссылка», когда пытаюсь использовать эту функцию.
Этот фрагмент кода примера воспроизводит ошибку:
abstract class Test {
private var test: Test? = null
fun getBla(): Test? {
return test
}
fun shout() {
println("Whaaaaa!")
}
}
fun main(args: Array<String>) {
val tst = Test.getBla()
tst.shout()
}
Ошибка читает Unresolved reference: getBla
Класс может не иметь такого большого смысла, но он предназначен для имитации структуры фактического класса, который я использую в своем приложении.
Я чувствую, что совершаю ужасную ошибку новичка. Я искал документацию по Stackoverflow и Kotlin, но не могу найти решение.
Я протестировал приведенный выше код на try.kotlinlang.org , просто заменив пример "hello world".
#### РЕДАКТИРОВАТЬ
Боюсь, контекст приложения, которое я пытаюсь создать, может быть важен в конце концов. Я пытаюсь реализовать базу данных Room, но самый понятный учебник, который я смог найти, касается Java, поэтому я пытаюсь перевести, и это заставляет меня сталкиваться с проблемами.
Это страница, на которой я сейчас следую: База данных комнат .
Мне нужно, чтобы класс «Test» здесь был единичным, для этого и было предназначено фактическое содержимое «getBla ()».
Чтобы перейти к актуальной проблеме, вот как выглядит настоящий класс:
@Database(entities = [(Box::class)], version = 1)
abstract class BoxRoomDatabase : RoomDatabase() {
abstract fun boxDao(): BoxDao
private var boxRoomDatabase: BoxRoomDatabase? = null
fun getDatabase(context: Context): BoxRoomDatabase? {
if (boxRoomDatabase == null) {
//Double colon allows to get the Java class instead of a KClass, which is not equivalent
synchronized<Unit>(BoxRoomDatabase::class.java) {
boxRoomDatabase = Room.databaseBuilder(context.applicationContext,
BoxRoomDatabase::class.java, "box_database")
.build()
}
}
return boxRoomDatabase
}
}
Итак, BoxRoomDatabase
должен быть синглтоном. Проблема возникает из-за автоматического перевода кода Java на Kotlin. Кажется, эта ситуация слишком сложна для этого. Я пытался найти ответ, ища различные комбинации «Kotlin», «Singleton» и «абстрактный метод». В конце концов я наткнулся на этот блог: Kotlin singletons с аргументом . Что мне было нужно, так это синглтон, который принимает аргумент, что, очевидно, не было тривиальной вещью в Котлине. В этом блоге объясняется, как реализовать такую конструкцию.
Мой код теперь по крайней мере компилируется, если он действительно делает то, что я хочу, я узнаю позже. Моя текущая реализация выглядит примерно так:
SingletonHolder.kt (для построения синглетонов с аргументами)
open class SingletonHolder<out T, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null
fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
BoxRoomDatabase.kt
import android.arch.persistence.room.RoomDatabase
import android.arch.persistence.room.Database
import android.content.Context
import android.arch.persistence.room.Room
@Database(entities = [(Box::class)], version = 1)
abstract class BoxRoomDatabase : RoomDatabase() {
abstract fun boxDao(): BoxDao
private var boxRoomDatabase: BoxRoomDatabase? = null
companion object : SingletonHolder<BoxRoomDatabase, Context>({
Room.databaseBuilder(it.applicationContext,
BoxRoomDatabase::class.java, "box_database")
.build()
})
}
BoxRepository.kt
class BoxRepository internal constructor(application: Application) {
private val mBoxDao: BoxDao
private val mAllBoxes: LiveData<List<Box>>
init {
mBoxDao = BoxRoomDatabase.getInstance(application).boxDao()
mAllBoxes = mBoxDao.getAllBoxes()
}
fun getAllBoxess(): LiveData<List<Box>> {
return mAllBoxes
}
fun insert(box: Box) {
InsertAsyncTask(mBoxDao).execute(box)
}
private class InsertAsyncTask internal constructor(private val mAsyncTaskDao: BoxDao) : AsyncTask<Box, Void, Void>() {
override fun doInBackground(vararg params: Box): Void? {
mAsyncTaskDao.insert(params[0])
return null
}
}
}
Даже если это компилируется, это может быть не лучшим способом сделать это. Если у кого-то есть какие-либо данные о структуре приведенного выше кода, не стесняйтесь поделиться своими данными.